Line data Source code
1 : // Copyright 2016 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef WASM_RUN_UTILS_H
6 : #define WASM_RUN_UTILS_H
7 :
8 : #include <setjmp.h>
9 : #include <stdint.h>
10 : #include <stdlib.h>
11 : #include <string.h>
12 : #include <array>
13 : #include <memory>
14 :
15 : #include "src/base/utils/random-number-generator.h"
16 : #include "src/compiler/compiler-source-position-table.h"
17 : #include "src/compiler/graph-visualizer.h"
18 : #include "src/compiler/int64-lowering.h"
19 : #include "src/compiler/js-graph.h"
20 : #include "src/compiler/node.h"
21 : #include "src/compiler/pipeline.h"
22 : #include "src/compiler/wasm-compiler.h"
23 : #include "src/compiler/zone-stats.h"
24 : #include "src/trap-handler/trap-handler.h"
25 : #include "src/wasm/function-body-decoder.h"
26 : #include "src/wasm/local-decl-encoder.h"
27 : #include "src/wasm/wasm-code-manager.h"
28 : #include "src/wasm/wasm-external-refs.h"
29 : #include "src/wasm/wasm-interpreter.h"
30 : #include "src/wasm/wasm-js.h"
31 : #include "src/wasm/wasm-module.h"
32 : #include "src/wasm/wasm-objects-inl.h"
33 : #include "src/wasm/wasm-objects.h"
34 : #include "src/wasm/wasm-opcodes.h"
35 : #include "src/wasm/wasm-tier.h"
36 : #include "src/zone/accounting-allocator.h"
37 : #include "src/zone/zone.h"
38 :
39 : #include "test/cctest/cctest.h"
40 : #include "test/cctest/compiler/call-tester.h"
41 : #include "test/cctest/compiler/graph-builder-tester.h"
42 : #include "test/cctest/compiler/value-helper.h"
43 : #include "test/common/wasm/flag-utils.h"
44 :
45 : namespace v8 {
46 : namespace internal {
47 : namespace wasm {
48 :
49 : constexpr uint32_t kMaxFunctions = 10;
50 : constexpr uint32_t kMaxGlobalsSize = 128;
51 :
52 : using compiler::CallDescriptor;
53 : using compiler::MachineTypeForC;
54 : using compiler::Node;
55 :
56 : // TODO(titzer): check traps more robustly in tests.
57 : // Currently, in tests, we just return 0xDEADBEEF from the function in which
58 : // the trap occurs if the runtime context is not available to throw a JavaScript
59 : // exception.
60 : #define CHECK_TRAP32(x) \
61 : CHECK_EQ(0xDEADBEEF, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
62 : #define CHECK_TRAP64(x) \
63 : CHECK_EQ(0xDEADBEEFDEADBEEF, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
64 : #define CHECK_TRAP(x) CHECK_TRAP32(x)
65 :
66 : #define WASM_WRAPPER_RETURN_VALUE 8754
67 :
68 : #define BUILD(r, ...) \
69 : do { \
70 : byte code[] = {__VA_ARGS__}; \
71 : r.Build(code, code + arraysize(code)); \
72 : } while (false)
73 :
74 : // For tests that must manually import a JSFunction with source code.
75 : struct ManuallyImportedJSFunction {
76 : FunctionSig* sig;
77 : Handle<JSFunction> js_function;
78 : };
79 :
80 : // A Wasm module builder. Globals are pre-set, however, memory and code may be
81 : // progressively added by a test. In turn, we piecemeal update the runtime
82 : // objects, i.e. {WasmInstanceObject}, {WasmModuleObject} and, if necessary,
83 : // the interpreter.
84 2188448 : class TestingModuleBuilder {
85 : public:
86 : TestingModuleBuilder(Zone*, ManuallyImportedJSFunction*, ExecutionTier,
87 : RuntimeExceptionSupport, LowerSimd);
88 :
89 384 : void ChangeOriginToAsmjs() { test_module_->origin = kAsmJsOrigin; }
90 :
91 : byte* AddMemory(uint32_t size, SharedFlag shared = SharedFlag::kNotShared);
92 :
93 : size_t CodeTableLength() const { return native_module_->num_functions(); }
94 :
95 : template <typename T>
96 : T* AddMemoryElems(uint32_t count) {
97 39992 : AddMemory(count * sizeof(T));
98 : return raw_mem_start<T>();
99 : }
100 :
101 : template <typename T>
102 : T* AddGlobal(
103 216 : ValueType type = ValueTypes::ValueTypeFor(MachineTypeForC<T>())) {
104 22144 : const WasmGlobal* global = AddGlobal(type);
105 22132 : return reinterpret_cast<T*>(globals_data_ + global->offset);
106 : }
107 :
108 3220 : byte AddSignature(FunctionSig* sig) {
109 : DCHECK_EQ(test_module_->signatures.size(),
110 : test_module_->signature_ids.size());
111 3220 : test_module_->signatures.push_back(sig);
112 3220 : auto canonical_sig_num = test_module_->signature_map.FindOrInsert(*sig);
113 3220 : test_module_->signature_ids.push_back(canonical_sig_num);
114 : size_t size = test_module_->signatures.size();
115 3220 : CHECK_GT(127, size);
116 3220 : return static_cast<byte>(size - 1);
117 : }
118 :
119 : uint32_t mem_size() { return mem_size_; }
120 :
121 : template <typename T>
122 : T* raw_mem_start() {
123 : DCHECK(mem_start_);
124 : return reinterpret_cast<T*>(mem_start_);
125 : }
126 :
127 : template <typename T>
128 : T* raw_mem_end() {
129 : DCHECK(mem_start_);
130 15924 : return reinterpret_cast<T*>(mem_start_ + mem_size_);
131 : }
132 :
133 : template <typename T>
134 : T raw_mem_at(int i) {
135 : DCHECK(mem_start_);
136 58560 : return ReadMemory(&(reinterpret_cast<T*>(mem_start_)[i]));
137 : }
138 :
139 : template <typename T>
140 : T raw_val_at(int i) {
141 792 : return ReadMemory(reinterpret_cast<T*>(mem_start_ + i));
142 : }
143 :
144 : template <typename T>
145 : void WriteMemory(T* p, T val) {
146 : WriteLittleEndianValue<T>(reinterpret_cast<Address>(p), val);
147 : }
148 :
149 : template <typename T>
150 : T ReadMemory(T* p) {
151 : return ReadLittleEndianValue<T>(reinterpret_cast<Address>(p));
152 : }
153 :
154 : // Zero-initialize the memory.
155 : void BlankMemory() {
156 : byte* raw = raw_mem_start<byte>();
157 624 : memset(raw, 0, mem_size_);
158 : }
159 :
160 : // Pseudo-randomly intialize the memory.
161 15564 : void RandomizeMemory(unsigned int seed = 88) {
162 : byte* raw = raw_mem_start<byte>();
163 : byte* end = raw_mem_end<byte>();
164 15564 : v8::base::RandomNumberGenerator rng;
165 15564 : rng.SetSeed(seed);
166 15564 : rng.NextBytes(raw, end - raw);
167 15564 : }
168 :
169 8 : void SetMaxMemPages(uint32_t maximum_pages) {
170 8 : test_module_->maximum_pages = maximum_pages;
171 8 : if (instance_object()->has_memory_object()) {
172 8 : instance_object()->memory_object()->set_maximum_pages(maximum_pages);
173 : }
174 8 : }
175 :
176 1208 : void SetHasSharedMemory() { test_module_->has_shared_memory = true; }
177 :
178 : enum FunctionType { kImport, kWasm };
179 : uint32_t AddFunction(FunctionSig* sig, const char* name, FunctionType type);
180 :
181 : // Wrap the code so it can be called as a JS function.
182 : Handle<JSFunction> WrapCode(uint32_t index);
183 :
184 : // If function_indexes is {nullptr}, the contents of the table will be
185 : // initialized with null functions.
186 : void AddIndirectFunctionTable(const uint16_t* function_indexes,
187 : uint32_t table_size);
188 :
189 : uint32_t AddBytes(Vector<const byte> bytes);
190 :
191 : uint32_t AddException(FunctionSig* sig);
192 :
193 : uint32_t AddPassiveDataSegment(Vector<const byte> bytes);
194 : uint32_t AddPassiveElementSegment(const std::vector<uint32_t>& entries);
195 :
196 : WasmFunction* GetFunctionAt(int index) {
197 1103308 : return &test_module_->functions[index];
198 : }
199 :
200 : WasmInterpreter* interpreter() const { return interpreter_; }
201 : bool interpret() const { return interpreter_ != nullptr; }
202 : LowerSimd lower_simd() const { return lower_simd_; }
203 : Isolate* isolate() const { return isolate_; }
204 : Handle<WasmInstanceObject> instance_object() const {
205 : return instance_object_;
206 : }
207 : WasmCode* GetFunctionCode(uint32_t index) const {
208 9612700 : return native_module_->GetCode(index);
209 : }
210 : Address globals_start() const {
211 : return reinterpret_cast<Address>(globals_data_);
212 : }
213 :
214 9617096 : void SetExecutable() { native_module_->SetExecutable(true); }
215 :
216 : CompilationEnv CreateCompilationEnv();
217 :
218 : ExecutionTier execution_tier() const { return execution_tier_; }
219 :
220 : RuntimeExceptionSupport runtime_exception_support() const {
221 : return runtime_exception_support_;
222 : }
223 :
224 : private:
225 : std::shared_ptr<WasmModule> test_module_;
226 : WasmModule* test_module_ptr_;
227 : Isolate* isolate_;
228 : WasmFeatures enabled_features_;
229 : uint32_t global_offset = 0;
230 : byte* mem_start_ = nullptr;
231 : uint32_t mem_size_ = 0;
232 : alignas(16) byte globals_data_[kMaxGlobalsSize];
233 : WasmInterpreter* interpreter_ = nullptr;
234 : ExecutionTier execution_tier_;
235 : Handle<WasmInstanceObject> instance_object_;
236 : NativeModule* native_module_ = nullptr;
237 : RuntimeExceptionSupport runtime_exception_support_;
238 : LowerSimd lower_simd_;
239 :
240 : // Data segment arrays that are normally allocated on the instance.
241 : std::vector<byte> data_segment_data_;
242 : std::vector<Address> data_segment_starts_;
243 : std::vector<uint32_t> data_segment_sizes_;
244 : std::vector<byte> dropped_data_segments_;
245 : std::vector<byte> dropped_elem_segments_;
246 :
247 : const WasmGlobal* AddGlobal(ValueType type);
248 :
249 : Handle<WasmInstanceObject> InitInstanceObject();
250 : };
251 :
252 : void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
253 : CompilationEnv* module, FunctionSig* sig,
254 : compiler::SourcePositionTable* source_position_table,
255 : const byte* start, const byte* end);
256 :
257 : class WasmFunctionWrapper : private compiler::GraphAndBuilders {
258 : public:
259 : WasmFunctionWrapper(Zone* zone, int num_params);
260 :
261 : void Init(CallDescriptor* call_descriptor, MachineType return_type,
262 : Vector<MachineType> param_types);
263 :
264 : template <typename ReturnType, typename... ParamTypes>
265 16552 : void Init(CallDescriptor* call_descriptor) {
266 : std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
267 16552 : {MachineTypeForC<ParamTypes>()...}};
268 : Vector<MachineType> param_vec(param_machine_types.data(),
269 : param_machine_types.size());
270 729312 : Init(call_descriptor, MachineTypeForC<ReturnType>(), param_vec);
271 16552 : }
272 :
273 9612676 : void SetInnerCode(WasmCode* code) {
274 : intptr_t address = static_cast<intptr_t>(code->instruction_start());
275 9612676 : compiler::NodeProperties::ChangeOp(
276 : inner_code_node_,
277 19225352 : common()->ExternalConstant(ExternalReference::FromRawAddress(address)));
278 9612676 : }
279 :
280 729312 : const compiler::Operator* IntPtrConstant(intptr_t value) {
281 : return machine()->Is32()
282 0 : ? common()->Int32Constant(static_cast<int32_t>(value))
283 1458624 : : common()->Int64Constant(static_cast<int64_t>(value));
284 : }
285 :
286 9612676 : void SetInstance(Handle<WasmInstanceObject> instance) {
287 19225352 : compiler::NodeProperties::ChangeOp(context_address_,
288 9612676 : common()->HeapConstant(instance));
289 9612676 : }
290 :
291 : Handle<Code> GetWrapperCode();
292 :
293 : Signature<MachineType>* signature() const { return signature_; }
294 :
295 : private:
296 : Node* inner_code_node_;
297 : Node* context_address_;
298 : MaybeHandle<Code> code_;
299 : Signature<MachineType>* signature_;
300 : };
301 :
302 : // A helper for compiling wasm functions for testing.
303 : // It contains the internal state for compilation (i.e. TurboFan graph) and
304 : // interpretation (by adding to the interpreter manually).
305 2206552 : class WasmFunctionCompiler : public compiler::GraphAndBuilders {
306 : public:
307 : ~WasmFunctionCompiler();
308 :
309 : Isolate* isolate() { return builder_->isolate(); }
310 729312 : CallDescriptor* descriptor() {
311 729312 : if (descriptor_ == nullptr) {
312 729312 : descriptor_ = compiler::GetWasmCallDescriptor(zone(), sig);
313 : }
314 729312 : return descriptor_;
315 : }
316 1102072 : uint32_t function_index() { return function_->func_index; }
317 :
318 : void Build(const byte* start, const byte* end);
319 :
320 : byte AllocateLocal(ValueType type) {
321 193928 : uint32_t index = local_decls.AddLocals(1, type);
322 5572 : byte result = static_cast<byte>(index);
323 : DCHECK_EQ(index, result);
324 : return result;
325 : }
326 :
327 424 : void SetSigIndex(int sig_index) { function_->sig_index = sig_index; }
328 :
329 : private:
330 : friend class WasmRunnerBase;
331 :
332 : WasmFunctionCompiler(Zone* zone, FunctionSig* sig,
333 : TestingModuleBuilder* builder, const char* name);
334 :
335 : compiler::JSGraph jsgraph;
336 : FunctionSig* sig;
337 : // The call descriptor is initialized when the function is compiled.
338 : CallDescriptor* descriptor_;
339 : TestingModuleBuilder* builder_;
340 : WasmFunction* function_;
341 : LocalDeclEncoder local_decls;
342 : compiler::SourcePositionTable source_position_table_;
343 : WasmInterpreter* interpreter_;
344 : };
345 :
346 : // A helper class to build a module around Wasm bytecode, generate machine
347 : // code, and run that code.
348 1094224 : class WasmRunnerBase : public HandleAndZoneScope {
349 : public:
350 1094224 : WasmRunnerBase(ManuallyImportedJSFunction* maybe_import,
351 : ExecutionTier execution_tier, int num_params,
352 : RuntimeExceptionSupport runtime_exception_support,
353 : LowerSimd lower_simd)
354 : : zone_(&allocator_, ZONE_NAME),
355 : builder_(&zone_, maybe_import, execution_tier,
356 : runtime_exception_support, lower_simd),
357 3282672 : wrapper_(&zone_, num_params) {}
358 :
359 : // Builds a graph from the given Wasm code and generates the machine
360 : // code and call wrapper for that graph. This method must not be called
361 : // more than once.
362 1088824 : void Build(const byte* start, const byte* end) {
363 1088824 : CHECK(!compiled_);
364 1088824 : compiled_ = true;
365 1088824 : functions_[0]->Build(start, end);
366 1088824 : }
367 :
368 : // Resets the state for building the next function.
369 : // The main function called will always be the first function.
370 : template <typename ReturnType, typename... ParamTypes>
371 1069420 : WasmFunctionCompiler& NewFunction(const char* name = nullptr) {
372 1094440 : return NewFunction(CreateSig<ReturnType, ParamTypes...>(), name);
373 : }
374 :
375 : // Resets the state for building the next function.
376 : // The main function called will be the last generated function.
377 : // Returns the index of the previously built function.
378 1103276 : WasmFunctionCompiler& NewFunction(FunctionSig* sig,
379 : const char* name = nullptr) {
380 3309828 : functions_.emplace_back(
381 2206552 : new WasmFunctionCompiler(&zone_, sig, &builder_, name));
382 1103276 : return *functions_.back();
383 : }
384 :
385 : byte AllocateLocal(ValueType type) {
386 : return functions_[0]->AllocateLocal(type);
387 : }
388 :
389 : uint32_t function_index() { return functions_[0]->function_index(); }
390 4707304 : WasmFunction* function() { return functions_[0]->function_; }
391 : WasmInterpreter* interpreter() {
392 : DCHECK(interpret());
393 4700028 : return functions_[0]->interpreter_;
394 : }
395 : bool possible_nondeterminism() { return possible_nondeterminism_; }
396 24 : TestingModuleBuilder& builder() { return builder_; }
397 : Zone* zone() { return &zone_; }
398 :
399 : bool interpret() { return builder_.interpret(); }
400 :
401 : template <typename ReturnType, typename... ParamTypes>
402 25056 : FunctionSig* CreateSig() {
403 : std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{
404 25056 : {MachineTypeForC<ParamTypes>()...}};
405 : Vector<MachineType> param_vec(param_machine_types.data(),
406 : param_machine_types.size());
407 1094476 : return CreateSig(MachineTypeForC<ReturnType>(), param_vec);
408 : }
409 :
410 : private:
411 : FunctionSig* CreateSig(MachineType return_type,
412 : Vector<MachineType> param_types);
413 :
414 : protected:
415 : v8::internal::AccountingAllocator allocator_;
416 : Zone zone_;
417 : TestingModuleBuilder builder_;
418 : std::vector<std::unique_ptr<WasmFunctionCompiler>> functions_;
419 : WasmFunctionWrapper wrapper_;
420 : bool compiled_ = false;
421 : bool possible_nondeterminism_ = false;
422 : int32_t main_fn_index_ = 0;
423 :
424 : public:
425 : // This field has to be static. Otherwise, gcc complains about the use in
426 : // the lambda context below.
427 : static bool trap_happened;
428 : };
429 :
430 : template <typename ReturnType, typename... ParamTypes>
431 2188448 : class WasmRunner : public WasmRunnerBase {
432 : public:
433 1094224 : WasmRunner(ExecutionTier execution_tier,
434 : ManuallyImportedJSFunction* maybe_import = nullptr,
435 : const char* main_fn_name = "main",
436 : RuntimeExceptionSupport runtime_exception_support =
437 : kNoRuntimeExceptionSupport,
438 : LowerSimd lower_simd = kNoLowerSimd)
439 : : WasmRunnerBase(maybe_import, execution_tier, sizeof...(ParamTypes),
440 1094224 : runtime_exception_support, lower_simd) {
441 : WasmFunctionCompiler& main_fn =
442 1069328 : NewFunction<ReturnType, ParamTypes...>(main_fn_name);
443 : // Non-zero if there is an import.
444 1094224 : main_fn_index_ = main_fn.function_index();
445 :
446 1094224 : if (!interpret()) {
447 729312 : wrapper_.Init<ReturnType, ParamTypes...>(main_fn.descriptor());
448 : }
449 1094224 : }
450 :
451 : WasmRunner(ExecutionTier execution_tier, LowerSimd lower_simd)
452 : : WasmRunner(execution_tier, nullptr, "main", kNoRuntimeExceptionSupport,
453 12772 : lower_simd) {}
454 :
455 : void SetUpTrapCallback() {
456 9620608 : WasmRunnerBase::trap_happened = false;
457 145520 : auto trap_callback = []() -> void {
458 72760 : WasmRunnerBase::trap_happened = true;
459 72760 : set_trap_callback_for_testing(nullptr);
460 0 : };
461 9620608 : set_trap_callback_for_testing(trap_callback);
462 : }
463 :
464 14312688 : ReturnType Call(ParamTypes... p) {
465 : DCHECK(compiled_);
466 14312688 : if (interpret()) return CallInterpreter(p...);
467 :
468 9612676 : ReturnType return_value = static_cast<ReturnType>(0xDEADBEEFDEADBEEF);
469 : SetUpTrapCallback();
470 :
471 19225352 : wrapper_.SetInnerCode(builder_.GetFunctionCode(main_fn_index_));
472 9612676 : wrapper_.SetInstance(builder_.instance_object());
473 : builder_.SetExecutable();
474 9612676 : Handle<Code> wrapper_code = wrapper_.GetWrapperCode();
475 : compiler::CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(),
476 : wrapper_code, wrapper_.signature());
477 : int32_t result;
478 : {
479 : SetThreadInWasmFlag();
480 :
481 9612676 : result = runner.Call(static_cast<void*>(&p)...,
482 : static_cast<void*>(&return_value));
483 :
484 : ClearThreadInWasmFlag();
485 : }
486 9612676 : CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result);
487 : return WasmRunnerBase::trap_happened
488 : ? static_cast<ReturnType>(0xDEADBEEFDEADBEEF)
489 9612676 : : return_value;
490 : }
491 :
492 4700012 : ReturnType CallInterpreter(ParamTypes... p) {
493 4700012 : WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
494 4700012 : thread->Reset();
495 : std::array<WasmValue, sizeof...(p)> args{{WasmValue(p)...}};
496 4700012 : thread->InitFrame(function(), args.data());
497 4700012 : thread->Run();
498 9400024 : CHECK_GT(thread->NumInterpretedCalls(), 0);
499 4700012 : if (thread->state() == WasmInterpreter::FINISHED) {
500 4663728 : WasmValue val = thread->GetReturnValue();
501 4663728 : possible_nondeterminism_ |= thread->PossibleNondeterminism();
502 : return val.to<ReturnType>();
503 36284 : } else if (thread->state() == WasmInterpreter::TRAPPED) {
504 : // TODO(titzer): return the correct trap code
505 : int64_t result = 0xDEADBEEFDEADBEEF;
506 0 : return static_cast<ReturnType>(result);
507 : } else {
508 : // TODO(titzer): falling off end
509 0 : return ReturnType{0};
510 : }
511 : }
512 :
513 7932 : void CheckCallApplyViaJS(double expected, uint32_t function_index,
514 : Handle<Object>* buffer, int count) {
515 : Isolate* isolate = builder_.isolate();
516 : SetUpTrapCallback();
517 7932 : if (jsfuncs_.size() <= function_index) {
518 4236 : jsfuncs_.resize(function_index + 1);
519 : }
520 7932 : if (jsfuncs_[function_index].is_null()) {
521 4272 : jsfuncs_[function_index] = builder_.WrapCode(function_index);
522 : }
523 7932 : Handle<JSFunction> jsfunc = jsfuncs_[function_index];
524 15864 : Handle<Object> global(isolate->context()->global_object(), isolate);
525 : MaybeHandle<Object> retval =
526 7932 : Execution::TryCall(isolate, jsfunc, global, count, buffer,
527 7932 : Execution::MessageHandling::kReport, nullptr);
528 :
529 7932 : if (retval.is_null() || WasmRunnerBase::trap_happened) {
530 2496 : CHECK_EQ(expected, static_cast<double>(0xDEADBEEF));
531 : } else {
532 : Handle<Object> result = retval.ToHandleChecked();
533 5436 : if (result->IsSmi()) {
534 3540 : CHECK_EQ(expected, Smi::ToInt(*result));
535 : } else {
536 1896 : CHECK(result->IsHeapNumber());
537 1896 : CHECK_DOUBLE_EQ(expected, HeapNumber::cast(*result)->value());
538 : }
539 : }
540 :
541 7932 : if (builder_.interpret()) {
542 5288 : CHECK_GT(builder_.interpreter()->GetThread(0)->NumInterpretedCalls(), 0);
543 : }
544 7932 : }
545 :
546 3036 : void CheckCallViaJS(double expected, ParamTypes... p) {
547 : Isolate* isolate = builder_.isolate();
548 : // MSVC doesn't allow empty arrays, so include a dummy at the end.
549 : Handle<Object> buffer[] = {isolate->factory()->NewNumber(p)...,
550 3000 : Handle<Object>()};
551 3036 : CheckCallApplyViaJS(expected, function()->func_index, buffer, sizeof...(p));
552 3036 : }
553 :
554 : Handle<Code> GetWrapperCode() { return wrapper_.GetWrapperCode(); }
555 :
556 : private:
557 : wasm::WasmCodeRefScope code_ref_scope_;
558 : std::vector<Handle<JSFunction>> jsfuncs_;
559 :
560 : void SetThreadInWasmFlag() {
561 9612676 : *reinterpret_cast<int*>(trap_handler::GetThreadInWasmThreadLocalAddress()) =
562 : true;
563 : }
564 :
565 : void ClearThreadInWasmFlag() {
566 9612676 : *reinterpret_cast<int*>(trap_handler::GetThreadInWasmThreadLocalAddress()) =
567 : false;
568 : }
569 : };
570 :
571 : // A macro to define tests that run in different engine configurations.
572 : #define WASM_EXEC_TEST(name) \
573 : void RunWasm_##name(ExecutionTier execution_tier); \
574 : TEST(RunWasmTurbofan_##name) { RunWasm_##name(ExecutionTier::kTurbofan); } \
575 : TEST(RunWasmLiftoff_##name) { RunWasm_##name(ExecutionTier::kLiftoff); } \
576 : TEST(RunWasmInterpreter_##name) { \
577 : RunWasm_##name(ExecutionTier::kInterpreter); \
578 : } \
579 : void RunWasm_##name(ExecutionTier execution_tier)
580 :
581 : #define WASM_COMPILED_EXEC_TEST(name) \
582 : void RunWasm_##name(ExecutionTier execution_tier); \
583 : TEST(RunWasmTurbofan_##name) { RunWasm_##name(ExecutionTier::kTurbofan); } \
584 : TEST(RunWasmLiftoff_##name) { RunWasm_##name(ExecutionTier::kLiftoff); } \
585 : void RunWasm_##name(ExecutionTier execution_tier)
586 :
587 : } // namespace wasm
588 : } // namespace internal
589 : } // namespace v8
590 :
591 : #endif
|