Line data Source code
1 : // Copyright 2017 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 : #include "test/cctest/wasm/wasm-run-utils.h"
6 :
7 : #include "src/assembler-inl.h"
8 : #include "src/code-tracer.h"
9 : #include "src/heap/heap-inl.h"
10 : #include "src/wasm/graph-builder-interface.h"
11 : #include "src/wasm/wasm-import-wrapper-cache-inl.h"
12 : #include "src/wasm/wasm-memory.h"
13 : #include "src/wasm/wasm-objects-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 : namespace wasm {
18 :
19 1093948 : TestingModuleBuilder::TestingModuleBuilder(
20 : Zone* zone, ManuallyImportedJSFunction* maybe_import, ExecutionTier tier,
21 : RuntimeExceptionSupport exception_support, LowerSimd lower_simd)
22 : : test_module_(std::make_shared<WasmModule>()),
23 : test_module_ptr_(test_module_.get()),
24 : isolate_(CcTest::InitIsolateOnce()),
25 : enabled_features_(WasmFeaturesFromIsolate(isolate_)),
26 : execution_tier_(tier),
27 : runtime_exception_support_(exception_support),
28 3281844 : lower_simd_(lower_simd) {
29 1093948 : WasmJs::Install(isolate_, true);
30 1093948 : test_module_->untagged_globals_buffer_size = kMaxGlobalsSize;
31 1093948 : memset(globals_data_, 0, sizeof(globals_data_));
32 :
33 : uint32_t maybe_import_index = 0;
34 1093948 : if (maybe_import) {
35 : // Manually add an imported function before any other functions.
36 : // This must happen before the instance object is created, since the
37 : // instance object allocates import entries.
38 2028 : maybe_import_index = AddFunction(maybe_import->sig, nullptr, kImport);
39 : DCHECK_EQ(0, maybe_import_index);
40 : }
41 :
42 1093948 : instance_object_ = InitInstanceObject();
43 1093948 : Handle<FixedArray> tables(isolate_->factory()->NewFixedArray(0));
44 1093948 : instance_object_->set_tables(*tables);
45 :
46 1093948 : if (maybe_import) {
47 : // Manually compile an import wrapper and insert it into the instance.
48 6084 : CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
49 4056 : auto kind = compiler::GetWasmImportCallKind(maybe_import->js_function,
50 2028 : maybe_import->sig, false);
51 4056 : auto import_wrapper = native_module_->import_wrapper_cache()->GetOrCompile(
52 4056 : isolate_->wasm_engine(), isolate_->counters(), kind, maybe_import->sig);
53 :
54 : ImportedFunctionEntry(instance_object_, maybe_import_index)
55 4056 : .SetWasmToJs(isolate_, maybe_import->js_function, import_wrapper);
56 : }
57 :
58 1093948 : if (tier == ExecutionTier::kInterpreter) {
59 364772 : interpreter_ = WasmDebugInfo::SetupForTesting(instance_object_);
60 : }
61 1093948 : }
62 :
63 41396 : byte* TestingModuleBuilder::AddMemory(uint32_t size, SharedFlag shared) {
64 41396 : CHECK(!test_module_->has_memory);
65 41396 : CHECK_NULL(mem_start_);
66 41396 : CHECK_EQ(0, mem_size_);
67 : DCHECK(!instance_object_->has_memory_object());
68 : DCHECK_IMPLIES(test_module_->origin == kWasmOrigin,
69 : size % kWasmPageSize == 0);
70 41396 : test_module_->has_memory = true;
71 : uint32_t max_size =
72 41396 : (test_module_->maximum_pages != 0) ? test_module_->maximum_pages : size;
73 : uint32_t alloc_size = RoundUp(size, kWasmPageSize);
74 : Handle<JSArrayBuffer> new_buffer;
75 41396 : if (shared == SharedFlag::kShared) {
76 16 : CHECK(NewSharedArrayBuffer(isolate_, alloc_size, max_size)
77 : .ToHandle(&new_buffer));
78 : } else {
79 82776 : CHECK(NewArrayBuffer(isolate_, alloc_size).ToHandle(&new_buffer));
80 : }
81 41396 : CHECK(!new_buffer.is_null());
82 41396 : mem_start_ = reinterpret_cast<byte*>(new_buffer->backing_store());
83 41396 : mem_size_ = size;
84 41396 : CHECK(size == 0 || mem_start_);
85 41396 : memset(mem_start_, 0, size);
86 :
87 : // Create the WasmMemoryObject.
88 : Handle<WasmMemoryObject> memory_object =
89 41396 : WasmMemoryObject::New(isolate_, new_buffer, max_size);
90 41396 : instance_object_->set_memory_object(*memory_object);
91 41396 : WasmMemoryObject::AddInstance(isolate_, memory_object, instance_object_);
92 : // TODO(wasm): Delete the following two lines when test-run-wasm will use a
93 : // multiple of kPageSize as memory size. At the moment, the effect of these
94 : // two lines is used to shrink the memory for testing purposes.
95 82792 : instance_object_->SetRawMemory(mem_start_, mem_size_);
96 41396 : return mem_start_;
97 : }
98 :
99 1104884 : uint32_t TestingModuleBuilder::AddFunction(FunctionSig* sig, const char* name,
100 : FunctionType type) {
101 1104884 : if (test_module_->functions.size() == 0) {
102 : // TODO(titzer): Reserving space here to avoid the underlying WasmFunction
103 : // structs from moving.
104 1093948 : test_module_->functions.reserve(kMaxFunctions);
105 : }
106 1104884 : uint32_t index = static_cast<uint32_t>(test_module_->functions.size());
107 3314652 : test_module_->functions.push_back({sig, index, 0, {0, 0}, false, false});
108 1104884 : if (type == kImport) {
109 : DCHECK_EQ(0, test_module_->num_declared_functions);
110 2028 : ++test_module_->num_imported_functions;
111 2028 : test_module_->functions.back().imported = true;
112 : } else {
113 1102856 : ++test_module_->num_declared_functions;
114 : }
115 : DCHECK_EQ(test_module_->functions.size(),
116 : test_module_->num_imported_functions +
117 : test_module_->num_declared_functions);
118 1104884 : if (name) {
119 1094352 : Vector<const byte> name_vec = Vector<const byte>::cast(CStrVector(name));
120 3283056 : test_module_->AddFunctionNameForTesting(
121 1094352 : index, {AddBytes(name_vec), static_cast<uint32_t>(name_vec.length())});
122 : }
123 1104884 : if (interpreter_) {
124 367408 : interpreter_->AddFunctionForTesting(&test_module_->functions.back());
125 : // Patch the jump table to call the interpreter for this function.
126 : wasm::WasmCompilationResult result = compiler::CompileWasmInterpreterEntry(
127 734816 : isolate_->wasm_engine(), native_module_->enabled_features(), index,
128 734816 : sig);
129 367408 : std::unique_ptr<wasm::WasmCode> code = native_module_->AddCode(
130 : index, result.code_desc, result.frame_slot_count,
131 : result.tagged_parameter_slots, std::move(result.protected_instructions),
132 : std::move(result.source_positions), wasm::WasmCode::kInterpreterEntry,
133 1837040 : wasm::WasmCode::kOther);
134 367408 : native_module_->PublishCode(std::move(code));
135 : }
136 : DCHECK_LT(index, kMaxFunctions); // limited for testing.
137 1104884 : return index;
138 : }
139 :
140 4324 : Handle<JSFunction> TestingModuleBuilder::WrapCode(uint32_t index) {
141 : SetExecutable();
142 8648 : FunctionSig* sig = test_module_->functions[index].sig;
143 : MaybeHandle<Code> maybe_ret_code =
144 4324 : compiler::CompileJSToWasmWrapper(isolate_, sig, false);
145 : Handle<Code> ret_code = maybe_ret_code.ToHandleChecked();
146 : Handle<JSFunction> ret = WasmExportedFunction::New(
147 : isolate_, instance_object(), MaybeHandle<String>(),
148 : static_cast<int>(index), static_cast<int>(sig->parameter_count()),
149 4324 : ret_code);
150 :
151 : // Add reference to the exported wrapper code.
152 : Handle<WasmModuleObject> module_object(instance_object()->module_object(),
153 4324 : isolate_);
154 4324 : Handle<FixedArray> old_arr(module_object->export_wrappers(), isolate_);
155 : Handle<FixedArray> new_arr =
156 4324 : isolate_->factory()->NewFixedArray(old_arr->length() + 1);
157 4324 : old_arr->CopyTo(0, *new_arr, 0, old_arr->length());
158 8648 : new_arr->set(old_arr->length(), *ret_code);
159 4324 : module_object->set_export_wrappers(*new_arr);
160 4324 : return ret;
161 : }
162 :
163 1600 : void TestingModuleBuilder::AddIndirectFunctionTable(
164 : const uint16_t* function_indexes, uint32_t table_size) {
165 : auto instance = instance_object();
166 : uint32_t table_index = static_cast<uint32_t>(test_module_->tables.size());
167 1600 : test_module_->tables.emplace_back();
168 : WasmTable& table = test_module_->tables.back();
169 1600 : table.initial_size = table_size;
170 1600 : table.maximum_size = table_size;
171 1600 : table.has_maximum_size = true;
172 1600 : table.type = kWasmAnyFunc;
173 : WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
174 1600 : instance_object(), table_size);
175 : Handle<WasmTableObject> table_obj =
176 1600 : WasmTableObject::New(isolate_, table.type, table.initial_size,
177 3200 : table.has_maximum_size, table.maximum_size, nullptr);
178 :
179 1600 : WasmTableObject::AddDispatchTable(isolate_, table_obj, instance_object_,
180 1600 : table_index);
181 :
182 1600 : if (function_indexes) {
183 804 : for (uint32_t i = 0; i < table_size; ++i) {
184 340 : WasmFunction& function = test_module_->functions[function_indexes[i]];
185 340 : int sig_id = test_module_->signature_map.Find(*function.sig);
186 : IndirectFunctionTableEntry(instance, i)
187 680 : .Set(sig_id, instance, function.func_index);
188 340 : WasmTableObject::SetFunctionTablePlaceholder(
189 680 : isolate_, table_obj, i, instance_object_, function_indexes[i]);
190 : }
191 : }
192 :
193 1600 : Handle<FixedArray> old_tables(instance_object_->tables(), isolate_);
194 1600 : Handle<FixedArray> new_tables = isolate_->factory()->CopyFixedArrayAndGrow(
195 3200 : old_tables, old_tables->length() + 1);
196 3200 : new_tables->set(old_tables->length(), *table_obj);
197 1600 : instance_object_->set_tables(*new_tables);
198 1600 : }
199 :
200 2191808 : uint32_t TestingModuleBuilder::AddBytes(Vector<const byte> bytes) {
201 2191808 : Vector<const uint8_t> old_bytes = native_module_->wire_bytes();
202 2191808 : uint32_t old_size = static_cast<uint32_t>(old_bytes.size());
203 : // Avoid placing strings at offset 0, this might be interpreted as "not
204 : // set", e.g. for function names.
205 2191808 : uint32_t bytes_offset = old_size ? old_size : 1;
206 2191808 : size_t new_size = bytes_offset + bytes.size();
207 : OwnedVector<uint8_t> new_bytes = OwnedVector<uint8_t>::New(new_size);
208 2191808 : if (old_size > 0) {
209 : memcpy(new_bytes.start(), old_bytes.start(), old_size);
210 : }
211 2191808 : memcpy(new_bytes.start() + bytes_offset, bytes.start(), bytes.length());
212 4383616 : native_module_->SetWireBytes(std::move(new_bytes));
213 2191808 : return bytes_offset;
214 : }
215 :
216 36 : uint32_t TestingModuleBuilder::AddException(FunctionSig* sig) {
217 : DCHECK_EQ(0, sig->return_count());
218 36 : uint32_t index = static_cast<uint32_t>(test_module_->exceptions.size());
219 72 : test_module_->exceptions.push_back(WasmException{sig});
220 36 : Handle<WasmExceptionTag> tag = WasmExceptionTag::New(isolate_, index);
221 36 : Handle<FixedArray> table(instance_object_->exceptions_table(), isolate_);
222 36 : table = isolate_->factory()->CopyFixedArrayAndGrow(table, 1);
223 36 : instance_object_->set_exceptions_table(*table);
224 72 : table->set(index, *tag);
225 36 : return index;
226 : }
227 :
228 60 : uint32_t TestingModuleBuilder::AddPassiveDataSegment(Vector<const byte> bytes) {
229 60 : uint32_t index = static_cast<uint32_t>(test_module_->data_segments.size());
230 : DCHECK_EQ(index, test_module_->data_segments.size());
231 : DCHECK_EQ(index, data_segment_starts_.size());
232 : DCHECK_EQ(index, data_segment_sizes_.size());
233 : DCHECK_EQ(index, dropped_data_segments_.size());
234 :
235 : // Add a passive data segment. This isn't used by function compilation, but
236 : // but it keeps the index in sync. The data segment's source will not be
237 : // correct, since we don't store data in the module wire bytes.
238 60 : test_module_->data_segments.emplace_back();
239 :
240 : // The num_declared_data_segments (from the DataCount section) is used
241 : // to validate the segment index, during function compilation.
242 60 : test_module_->num_declared_data_segments = index + 1;
243 :
244 : Address old_data_address =
245 60 : reinterpret_cast<Address>(data_segment_data_.data());
246 : size_t old_data_size = data_segment_data_.size();
247 60 : data_segment_data_.resize(old_data_size + bytes.length());
248 : Address new_data_address =
249 60 : reinterpret_cast<Address>(data_segment_data_.data());
250 :
251 60 : memcpy(data_segment_data_.data() + old_data_size, bytes.start(),
252 : bytes.length());
253 :
254 : // The data_segment_data_ offset may have moved, so update all the starts.
255 60 : for (Address& start : data_segment_starts_) {
256 0 : start += new_data_address - old_data_address;
257 : }
258 120 : data_segment_starts_.push_back(new_data_address + old_data_size);
259 120 : data_segment_sizes_.push_back(bytes.length());
260 120 : dropped_data_segments_.push_back(0);
261 :
262 : // The vector pointers may have moved, so update the instance object.
263 : instance_object_->set_data_segment_starts(data_segment_starts_.data());
264 : instance_object_->set_data_segment_sizes(data_segment_sizes_.data());
265 : instance_object_->set_dropped_data_segments(dropped_data_segments_.data());
266 60 : return index;
267 : }
268 :
269 731528 : CompilationEnv TestingModuleBuilder::CreateCompilationEnv() {
270 : return {
271 731528 : test_module_ptr_,
272 : trap_handler::IsTrapHandlerEnabled() ? kUseTrapHandler : kNoTrapHandler,
273 1463056 : runtime_exception_support_, enabled_features_, lower_simd()};
274 : }
275 :
276 22240 : const WasmGlobal* TestingModuleBuilder::AddGlobal(ValueType type) {
277 22240 : byte size = ValueTypes::MemSize(ValueTypes::MachineTypeFor(type));
278 22240 : global_offset = (global_offset + size - 1) & ~(size - 1); // align
279 66720 : test_module_->globals.push_back(
280 : {type, true, WasmInitExpr(), {global_offset}, false, false});
281 22240 : global_offset += size;
282 : // limit number of globals.
283 22240 : CHECK_LT(global_offset, kMaxGlobalsSize);
284 22240 : return &test_module_->globals.back();
285 : }
286 :
287 1093948 : Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() {
288 : Handle<Script> script =
289 2187896 : isolate_->factory()->NewScript(isolate_->factory()->empty_string());
290 : script->set_type(Script::TYPE_WASM);
291 : Handle<WasmModuleObject> module_object =
292 : WasmModuleObject::New(isolate_, enabled_features_, test_module_, {},
293 4375792 : script, Handle<ByteArray>::null());
294 : // This method is called when we initialize TestEnvironment. We don't
295 : // have a memory yet, so we won't create it here. We'll update the
296 : // interpreter when we get a memory. We do have globals, though.
297 1093948 : native_module_ = module_object->native_module();
298 1093948 : native_module_->ReserveCodeTableForTesting(kMaxFunctions);
299 :
300 1093948 : auto instance = WasmInstanceObject::New(isolate_, module_object);
301 2187896 : instance->set_exceptions_table(*isolate_->factory()->empty_fixed_array());
302 1093948 : instance->set_globals_start(globals_data_);
303 1093948 : return instance;
304 : }
305 :
306 492 : void TestBuildingGraphWithBuilder(compiler::WasmGraphBuilder* builder,
307 : Zone* zone, FunctionSig* sig,
308 : const byte* start, const byte* end) {
309 492 : WasmFeatures unused_detected_features;
310 : FunctionBody body(sig, 0, start, end);
311 : DecodeResult result =
312 984 : BuildTFGraph(zone->allocator(), kAllWasmFeatures, nullptr, builder,
313 : &unused_detected_features, body, nullptr);
314 492 : if (result.failed()) {
315 : #ifdef DEBUG
316 : if (!FLAG_trace_wasm_decoder) {
317 : // Retry the compilation with the tracing flag on, to help in debugging.
318 : FLAG_trace_wasm_decoder = true;
319 : result = BuildTFGraph(zone->allocator(), kAllWasmFeatures, nullptr,
320 : builder, &unused_detected_features, body, nullptr);
321 : }
322 : #endif
323 :
324 : FATAL("Verification failed; pc = +%x, msg = %s", result.error().offset(),
325 0 : result.error().message().c_str());
326 : }
327 492 : builder->LowerInt64();
328 492 : if (!CpuFeatures::SupportsWasmSimd128()) {
329 0 : builder->SimdScalarLoweringForTesting();
330 : }
331 492 : }
332 :
333 492 : void TestBuildingGraph(Zone* zone, compiler::JSGraph* jsgraph,
334 : CompilationEnv* module, FunctionSig* sig,
335 : compiler::SourcePositionTable* source_position_table,
336 : const byte* start, const byte* end) {
337 : compiler::WasmGraphBuilder builder(module, zone, jsgraph, sig,
338 492 : source_position_table);
339 492 : TestBuildingGraphWithBuilder(&builder, zone, sig, start, end);
340 492 : }
341 :
342 1093948 : WasmFunctionWrapper::WasmFunctionWrapper(Zone* zone, int num_params)
343 : : GraphAndBuilders(zone),
344 : inner_code_node_(nullptr),
345 : context_address_(nullptr),
346 2187896 : signature_(nullptr) {
347 : // One additional parameter for the pointer to the return value memory.
348 1093948 : Signature<MachineType>::Builder sig_builder(zone, 1, num_params + 1);
349 :
350 : sig_builder.AddReturn(MachineType::Int32());
351 3347564 : for (int i = 0; i < num_params + 1; i++) {
352 : sig_builder.AddParam(MachineType::Pointer());
353 : }
354 1093948 : signature_ = sig_builder.Build();
355 1093948 : }
356 :
357 729176 : void WasmFunctionWrapper::Init(CallDescriptor* call_descriptor,
358 : MachineType return_type,
359 : Vector<MachineType> param_types) {
360 : DCHECK_NOT_NULL(call_descriptor);
361 : DCHECK_EQ(signature_->parameter_count(), param_types.length() + 1);
362 :
363 : // Create the TF graph for the wrapper.
364 :
365 : // Function, context_address, effect, and control.
366 729176 : Node** parameters = zone()->NewArray<Node*>(param_types.length() + 4);
367 : int start_value_output_count =
368 729176 : static_cast<int>(signature_->parameter_count()) + 1;
369 729176 : graph()->SetStart(
370 : graph()->NewNode(common()->Start(start_value_output_count)));
371 : Node* effect = graph()->start();
372 : int parameter_count = 0;
373 :
374 : // Dummy node which gets replaced in SetInnerCode.
375 1458352 : inner_code_node_ = graph()->NewNode(common()->Int32Constant(0));
376 729176 : parameters[parameter_count++] = inner_code_node_;
377 :
378 : // Dummy node that gets replaced in SetContextAddress.
379 1458352 : context_address_ = graph()->NewNode(IntPtrConstant(0));
380 729176 : parameters[parameter_count++] = context_address_;
381 :
382 : int param_idx = 0;
383 773032 : for (MachineType t : param_types) {
384 : DCHECK_NE(MachineType::None(), t);
385 65784 : parameters[parameter_count] = graph()->NewNode(
386 : machine()->Load(t),
387 : graph()->NewNode(common()->Parameter(param_idx++), graph()->start()),
388 21928 : graph()->NewNode(common()->Int32Constant(0)), effect, graph()->start());
389 21928 : effect = parameters[parameter_count++];
390 : }
391 :
392 729176 : parameters[parameter_count++] = effect;
393 729176 : parameters[parameter_count++] = graph()->start();
394 729176 : Node* call = graph()->NewNode(common()->Call(call_descriptor),
395 729176 : parameter_count, parameters);
396 :
397 729176 : if (!return_type.IsNone()) {
398 2900992 : effect = graph()->NewNode(
399 : machine()->Store(compiler::StoreRepresentation(
400 : return_type.representation(), WriteBarrierKind::kNoWriteBarrier)),
401 : graph()->NewNode(common()->Parameter(param_types.length()),
402 : graph()->start()),
403 : graph()->NewNode(common()->Int32Constant(0)), call, effect,
404 : graph()->start());
405 : }
406 729176 : Node* zero = graph()->NewNode(common()->Int32Constant(0));
407 1458352 : Node* r = graph()->NewNode(
408 : common()->Return(), zero,
409 : graph()->NewNode(common()->Int32Constant(WASM_WRAPPER_RETURN_VALUE)),
410 : effect, graph()->start());
411 729176 : graph()->SetEnd(graph()->NewNode(common()->End(1), r));
412 729176 : }
413 :
414 9607416 : Handle<Code> WasmFunctionWrapper::GetWrapperCode() {
415 : Handle<Code> code;
416 9607416 : if (!code_.ToHandle(&code)) {
417 : Isolate* isolate = CcTest::InitIsolateOnce();
418 :
419 : auto call_descriptor =
420 724876 : compiler::Linkage::GetSimplifiedCDescriptor(zone(), signature_, true);
421 :
422 : if (kSystemPointerSize == 4) {
423 : size_t num_params = signature_->parameter_count();
424 : // One additional parameter for the pointer of the return value.
425 : Signature<MachineRepresentation>::Builder rep_builder(zone(), 1,
426 : num_params + 1);
427 :
428 : rep_builder.AddReturn(MachineRepresentation::kWord32);
429 : for (size_t i = 0; i < num_params + 1; i++) {
430 : rep_builder.AddParam(MachineRepresentation::kWord32);
431 : }
432 : compiler::Int64Lowering r(graph(), machine(), common(), zone(),
433 : rep_builder.Build());
434 : r.LowerGraph();
435 : }
436 :
437 : OptimizedCompilationInfo info(ArrayVector("testing"), graph()->zone(),
438 1449752 : Code::C_WASM_ENTRY);
439 : code_ = compiler::Pipeline::GenerateCodeForTesting(
440 : &info, isolate, call_descriptor, graph(),
441 724876 : AssemblerOptions::Default(isolate));
442 : code = code_.ToHandleChecked();
443 : #ifdef ENABLE_DISASSEMBLER
444 : if (FLAG_print_opt_code) {
445 : CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
446 : OFStream os(tracing_scope.file());
447 :
448 : code->Disassemble("wasm wrapper", os);
449 : }
450 : #endif
451 : }
452 :
453 9607416 : return code;
454 : }
455 :
456 1097456 : void WasmFunctionCompiler::Build(const byte* start, const byte* end) {
457 1097456 : size_t locals_size = local_decls.Size();
458 1097456 : size_t total_size = end - start + locals_size + 1;
459 1097456 : byte* buffer = static_cast<byte*>(zone()->New(total_size));
460 : // Prepend the local decls to the code.
461 1097456 : local_decls.Emit(buffer);
462 : // Emit the code.
463 1097456 : memcpy(buffer + locals_size, start, end - start);
464 : // Append an extra end opcode.
465 1097456 : buffer[total_size - 1] = kExprEnd;
466 :
467 : start = buffer;
468 1097456 : end = buffer + total_size;
469 :
470 1097456 : CHECK_GE(kMaxInt, end - start);
471 1097456 : int len = static_cast<int>(end - start);
472 2194912 : function_->code = {builder_->AddBytes(Vector<const byte>(start, len)),
473 2194912 : static_cast<uint32_t>(len)};
474 :
475 1097456 : if (interpreter_) {
476 : // Add the code to the interpreter; do not generate compiled code.
477 365928 : interpreter_->SetFunctionCodeForTesting(function_, start, end);
478 365928 : return;
479 : }
480 :
481 731528 : Vector<const uint8_t> wire_bytes = builder_->instance_object()
482 1463056 : ->module_object()
483 : ->native_module()
484 731528 : ->wire_bytes();
485 :
486 731528 : CompilationEnv env = builder_->CreateCompilationEnv();
487 731528 : ScopedVector<uint8_t> func_wire_bytes(function_->code.length());
488 731528 : memcpy(func_wire_bytes.start(), wire_bytes.start() + function_->code.offset(),
489 : func_wire_bytes.length());
490 :
491 : FunctionBody func_body{function_->sig, function_->code.offset(),
492 : func_wire_bytes.start(), func_wire_bytes.end()};
493 : NativeModule* native_module =
494 1463056 : builder_->instance_object()->module_object()->native_module();
495 731528 : WasmCompilationUnit unit(isolate()->wasm_engine(), function_->func_index,
496 2194584 : builder_->execution_tier());
497 731528 : WasmFeatures unused_detected_features;
498 : WasmCompilationResult result = unit.ExecuteCompilation(
499 1463056 : &env, native_module->compilation_state()->GetWireBytesStorage(),
500 1463056 : isolate()->counters(), &unused_detected_features);
501 731528 : WasmCode* code = native_module->AddCompiledCode(std::move(result));
502 : DCHECK_NOT_NULL(code);
503 731528 : if (WasmCode::ShouldBeLogged(isolate())) code->LogCode(isolate());
504 : }
505 :
506 1102856 : WasmFunctionCompiler::WasmFunctionCompiler(Zone* zone, FunctionSig* sig,
507 : TestingModuleBuilder* builder,
508 : const char* name)
509 : : GraphAndBuilders(zone),
510 : jsgraph(builder->isolate(), this->graph(), this->common(), nullptr,
511 : nullptr, this->machine()),
512 : sig(sig),
513 : descriptor_(nullptr),
514 : builder_(builder),
515 : local_decls(zone, sig),
516 : source_position_table_(this->graph()),
517 3308568 : interpreter_(builder->interpreter()) {
518 : // Get a new function from the testing module.
519 1102856 : int index = builder->AddFunction(sig, name, TestingModuleBuilder::kWasm);
520 2205712 : function_ = builder_->GetFunctionAt(index);
521 1102856 : }
522 :
523 : WasmFunctionCompiler::~WasmFunctionCompiler() = default;
524 :
525 1094200 : FunctionSig* WasmRunnerBase::CreateSig(MachineType return_type,
526 : Vector<MachineType> param_types) {
527 1094200 : int return_count = return_type.IsNone() ? 0 : 1;
528 : int param_count = param_types.length();
529 :
530 : // Allocate storage array in zone.
531 1094200 : ValueType* sig_types = zone_.NewArray<ValueType>(return_count + param_count);
532 :
533 : // Convert machine types to local types, and check that there are no
534 : // MachineType::None()'s in the parameters.
535 : int idx = 0;
536 1094200 : if (return_count) sig_types[idx++] = ValueTypes::ValueTypeFor(return_type);
537 1160576 : for (MachineType param : param_types) {
538 33188 : CHECK_NE(MachineType::None(), param);
539 33188 : sig_types[idx++] = ValueTypes::ValueTypeFor(param);
540 : }
541 2188400 : return new (&zone_) FunctionSig(return_count, param_count, sig_types);
542 : }
543 :
544 : // static
545 : bool WasmRunnerBase::trap_happened;
546 :
547 : } // namespace wasm
548 : } // namespace internal
549 78189 : } // namespace v8
|