OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/isolate-inl.h" | 9 #include "src/isolate-inl.h" |
10 | 10 |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 return BuildTrapCode(reason_node, position_node); | 294 return BuildTrapCode(reason_node, position_node); |
295 } | 295 } |
296 // Connect the current control and effect to the existing trap code. | 296 // Connect the current control and effect to the existing trap code. |
297 builder_->AppendToMerge(trap_merge_, builder_->Control()); | 297 builder_->AppendToMerge(trap_merge_, builder_->Control()); |
298 builder_->AppendToPhi(trap_effect_, builder_->Effect()); | 298 builder_->AppendToPhi(trap_effect_, builder_->Effect()); |
299 builder_->AppendToPhi(trap_reason_, reason_node); | 299 builder_->AppendToPhi(trap_reason_, reason_node); |
300 builder_->AppendToPhi(trap_position_, position_node); | 300 builder_->AppendToPhi(trap_position_, position_node); |
301 } | 301 } |
302 | 302 |
303 void BuildTrapCode(Node* reason_node, Node* position_node) { | 303 void BuildTrapCode(Node* reason_node, Node* position_node) { |
304 Node* end; | |
305 Node** control_ptr = builder_->control_; | 304 Node** control_ptr = builder_->control_; |
306 Node** effect_ptr = builder_->effect_; | 305 Node** effect_ptr = builder_->effect_; |
307 wasm::ModuleEnv* module = builder_->module_; | 306 wasm::ModuleEnv* module = builder_->module_; |
308 DCHECK(trap_merge_ == NULL); | 307 DCHECK(trap_merge_ == NULL); |
309 *control_ptr = trap_merge_ = | 308 *control_ptr = trap_merge_ = |
310 graph()->NewNode(common()->Merge(1), *control_ptr); | 309 graph()->NewNode(common()->Merge(1), *control_ptr); |
311 *effect_ptr = trap_effect_ = | 310 *effect_ptr = trap_effect_ = |
312 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); | 311 graph()->NewNode(common()->EffectPhi(1), *effect_ptr, *control_ptr); |
313 trap_reason_ = | 312 trap_reason_ = |
314 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), | 313 graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 1), |
(...skipping 10 matching lines...) Expand all Loading... |
325 trap_position_smi}; // byte position | 324 trap_position_smi}; // byte position |
326 BuildCallToRuntime(Runtime::kThrowWasmError, jsgraph(), | 325 BuildCallToRuntime(Runtime::kThrowWasmError, jsgraph(), |
327 module->instance->context, parameters, | 326 module->instance->context, parameters, |
328 arraysize(parameters), effect_ptr, *control_ptr); | 327 arraysize(parameters), effect_ptr, *control_ptr); |
329 } | 328 } |
330 if (false) { | 329 if (false) { |
331 // End the control flow with a throw | 330 // End the control flow with a throw |
332 Node* thrw = | 331 Node* thrw = |
333 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), | 332 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), |
334 *effect_ptr, *control_ptr); | 333 *effect_ptr, *control_ptr); |
335 end = thrw; | 334 MergeControlToEnd(jsgraph(), thrw); |
336 } else { | 335 } else { |
337 // End the control flow with returning 0xdeadbeef | 336 // End the control flow with returning 0xdeadbeef |
338 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); | 337 Node* ret_value = GetTrapValue(builder_->GetFunctionSignature()); |
339 end = graph()->NewNode(jsgraph()->common()->Return(), | 338 builder_->Return(ret_value); |
340 jsgraph()->Int32Constant(0), ret_value, | |
341 *effect_ptr, *control_ptr); | |
342 } | 339 } |
343 | |
344 MergeControlToEnd(jsgraph(), end); | |
345 } | 340 } |
346 }; | 341 }; |
347 | 342 |
348 WasmGraphBuilder::WasmGraphBuilder( | 343 WasmGraphBuilder::WasmGraphBuilder( |
349 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* sig, | 344 Zone* zone, JSGraph* jsgraph, wasm::FunctionSig* sig, |
350 compiler::SourcePositionTable* source_position_table) | 345 compiler::SourcePositionTable* source_position_table) |
351 : zone_(zone), | 346 : zone_(zone), |
352 jsgraph_(jsgraph), | 347 jsgraph_(jsgraph), |
353 function_tables_(zone), | 348 function_tables_(zone), |
354 function_table_sizes_(zone), | 349 function_table_sizes_(zone), |
(...skipping 12 matching lines...) Expand all Loading... |
367 } | 362 } |
368 | 363 |
369 Node* WasmGraphBuilder::Error() { return jsgraph()->Dead(); } | 364 Node* WasmGraphBuilder::Error() { return jsgraph()->Dead(); } |
370 | 365 |
371 Node* WasmGraphBuilder::Start(unsigned params) { | 366 Node* WasmGraphBuilder::Start(unsigned params) { |
372 Node* start = graph()->NewNode(jsgraph()->common()->Start(params)); | 367 Node* start = graph()->NewNode(jsgraph()->common()->Start(params)); |
373 graph()->SetStart(start); | 368 graph()->SetStart(start); |
374 return start; | 369 return start; |
375 } | 370 } |
376 | 371 |
377 Node* WasmGraphBuilder::Param(unsigned index, wasm::LocalType type) { | 372 Node* WasmGraphBuilder::Param(unsigned index) { |
378 return graph()->NewNode(jsgraph()->common()->Parameter(index), | 373 return graph()->NewNode(jsgraph()->common()->Parameter(index), |
379 graph()->start()); | 374 graph()->start()); |
380 } | 375 } |
381 | 376 |
382 Node* WasmGraphBuilder::Loop(Node* entry) { | 377 Node* WasmGraphBuilder::Loop(Node* entry) { |
383 return graph()->NewNode(jsgraph()->common()->Loop(1), entry); | 378 return graph()->NewNode(jsgraph()->common()->Loop(1), entry); |
384 } | 379 } |
385 | 380 |
386 Node* WasmGraphBuilder::Terminate(Node* effect, Node* control) { | 381 Node* WasmGraphBuilder::Terminate(Node* effect, Node* control) { |
387 Node* terminate = | 382 Node* terminate = |
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 | 1087 |
1093 Node* WasmGraphBuilder::IfDefault(Node* sw) { | 1088 Node* WasmGraphBuilder::IfDefault(Node* sw) { |
1094 DCHECK_EQ(IrOpcode::kSwitch, sw->opcode()); | 1089 DCHECK_EQ(IrOpcode::kSwitch, sw->opcode()); |
1095 return graph()->NewNode(jsgraph()->common()->IfDefault(), sw); | 1090 return graph()->NewNode(jsgraph()->common()->IfDefault(), sw); |
1096 } | 1091 } |
1097 | 1092 |
1098 Node* WasmGraphBuilder::Return(unsigned count, Node** vals) { | 1093 Node* WasmGraphBuilder::Return(unsigned count, Node** vals) { |
1099 DCHECK_NOT_NULL(*control_); | 1094 DCHECK_NOT_NULL(*control_); |
1100 DCHECK_NOT_NULL(*effect_); | 1095 DCHECK_NOT_NULL(*effect_); |
1101 | 1096 |
1102 Node** buf = Realloc(vals, count, count + 3); | 1097 static const int kStackAllocatedNodeBufferSize = 8; |
1103 memmove(buf + 1, buf, sizeof(void*) * count); | 1098 Node* stack_buffer[kStackAllocatedNodeBufferSize]; |
| 1099 std::vector<Node*> heap_buffer; |
| 1100 |
| 1101 Node** buf = stack_buffer; |
| 1102 if (count + 3 > kStackAllocatedNodeBufferSize) { |
| 1103 heap_buffer.resize(count + 3); |
| 1104 buf = heap_buffer.data(); |
| 1105 } |
| 1106 |
1104 buf[0] = jsgraph()->Int32Constant(0); | 1107 buf[0] = jsgraph()->Int32Constant(0); |
| 1108 memcpy(buf + 1, vals, sizeof(void*) * count); |
1105 buf[count + 1] = *effect_; | 1109 buf[count + 1] = *effect_; |
1106 buf[count + 2] = *control_; | 1110 buf[count + 2] = *control_; |
1107 Node* ret = | 1111 Node* ret = |
1108 graph()->NewNode(jsgraph()->common()->Return(count), count + 3, buf); | 1112 graph()->NewNode(jsgraph()->common()->Return(count), count + 3, buf); |
1109 | 1113 |
1110 MergeControlToEnd(jsgraph(), ret); | 1114 MergeControlToEnd(jsgraph(), ret); |
1111 return ret; | 1115 return ret; |
1112 } | 1116 } |
1113 | 1117 |
1114 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); } | 1118 Node* WasmGraphBuilder::ReturnVoid() { return Return(0, Buffer(0)); } |
(...skipping 1641 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2756 Node* context = graph()->NewNode( | 2760 Node* context = graph()->NewNode( |
2757 jsgraph()->common()->Parameter( | 2761 jsgraph()->common()->Parameter( |
2758 Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), | 2762 Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"), |
2759 graph()->start()); | 2763 graph()->start()); |
2760 | 2764 |
2761 int pos = 0; | 2765 int pos = 0; |
2762 args[pos++] = HeapConstant(wasm_code); | 2766 args[pos++] = HeapConstant(wasm_code); |
2763 | 2767 |
2764 // Convert JS parameters to WASM numbers. | 2768 // Convert JS parameters to WASM numbers. |
2765 for (int i = 0; i < wasm_count; ++i) { | 2769 for (int i = 0; i < wasm_count; ++i) { |
2766 Node* param = | 2770 Node* param = Param(i + 1); |
2767 graph()->NewNode(jsgraph()->common()->Parameter(i + 1), start); | |
2768 Node* wasm_param = FromJS(param, context, sig->GetParam(i)); | 2771 Node* wasm_param = FromJS(param, context, sig->GetParam(i)); |
2769 args[pos++] = wasm_param; | 2772 args[pos++] = wasm_param; |
2770 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { | 2773 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { |
2771 // We make up the high word with SAR to get the proper sign extension. | 2774 // We make up the high word with SAR to get the proper sign extension. |
2772 args[pos++] = graph()->NewNode(jsgraph()->machine()->Word32Sar(), | 2775 args[pos++] = graph()->NewNode(jsgraph()->machine()->Word32Sar(), |
2773 wasm_param, jsgraph()->Int32Constant(31)); | 2776 wasm_param, jsgraph()->Int32Constant(31)); |
2774 } | 2777 } |
2775 } | 2778 } |
2776 | 2779 |
2777 args[pos++] = *effect_; | 2780 args[pos++] = *effect_; |
2778 args[pos++] = *control_; | 2781 args[pos++] = *control_; |
2779 | 2782 |
2780 // Call the WASM code. | 2783 // Call the WASM code. |
2781 CallDescriptor* desc = | 2784 CallDescriptor* desc = |
2782 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); | 2785 wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig); |
2783 if (jsgraph()->machine()->Is32()) { | 2786 if (jsgraph()->machine()->Is32()) { |
2784 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc); | 2787 desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc); |
2785 } | 2788 } |
2786 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); | 2789 Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args); |
| 2790 *effect_ = call; |
2787 Node* retval = call; | 2791 Node* retval = call; |
2788 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && | 2792 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && |
2789 sig->GetReturn(0) == wasm::kAstI64) { | 2793 sig->GetReturn(0) == wasm::kAstI64) { |
2790 // The return values comes as two values, we pick the low word. | 2794 // The return values comes as two values, we pick the low word. |
2791 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, | 2795 retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval, |
2792 graph()->start()); | 2796 graph()->start()); |
2793 } | 2797 } |
2794 Node* jsval = ToJS( | 2798 Node* jsval = ToJS( |
2795 retval, sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); | 2799 retval, sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn()); |
2796 Node* ret = graph()->NewNode(jsgraph()->common()->Return(), | 2800 Return(jsval); |
2797 jsgraph()->Int32Constant(0), jsval, call, start); | |
2798 | |
2799 MergeControlToEnd(jsgraph(), ret); | |
2800 } | 2801 } |
2801 | 2802 |
2802 int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count, | 2803 int WasmGraphBuilder::AddParameterNodes(Node** args, int pos, int param_count, |
2803 wasm::FunctionSig* sig) { | 2804 wasm::FunctionSig* sig) { |
2804 // Convert WASM numbers to JS values. | 2805 // Convert WASM numbers to JS values. |
2805 int param_index = 0; | 2806 int param_index = 0; |
2806 for (int i = 0; i < param_count; ++i) { | 2807 for (int i = 0; i < param_count; ++i) { |
2807 Node* param = graph()->NewNode( | 2808 Node* param = Param(param_index++); |
2808 jsgraph()->common()->Parameter(param_index++), graph()->start()); | |
2809 args[pos++] = ToJS(param, sig->GetParam(i)); | 2809 args[pos++] = ToJS(param, sig->GetParam(i)); |
2810 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { | 2810 if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) { |
2811 // On 32 bit platforms we have to skip the high word of int64 | 2811 // On 32 bit platforms we have to skip the high word of int64 |
2812 // parameters. | 2812 // parameters. |
2813 param_index++; | 2813 param_index++; |
2814 } | 2814 } |
2815 } | 2815 } |
2816 return pos; | 2816 return pos; |
2817 } | 2817 } |
2818 | 2818 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2902 | 2902 |
2903 *effect_ = call; | 2903 *effect_ = call; |
2904 SetSourcePosition(call, 0); | 2904 SetSourcePosition(call, 0); |
2905 | 2905 |
2906 // Convert the return value back. | 2906 // Convert the return value back. |
2907 Node* i32_zero = jsgraph()->Int32Constant(0); | 2907 Node* i32_zero = jsgraph()->Int32Constant(0); |
2908 Node* val = sig->return_count() == 0 | 2908 Node* val = sig->return_count() == 0 |
2909 ? i32_zero | 2909 ? i32_zero |
2910 : FromJS(call, HeapConstant(isolate->native_context()), | 2910 : FromJS(call, HeapConstant(isolate->native_context()), |
2911 sig->GetReturn()); | 2911 sig->GetReturn()); |
2912 Node* ret = graph()->NewNode(jsgraph()->common()->Return(), i32_zero, val, | 2912 Return(val); |
2913 *effect_, start); | |
2914 | |
2915 MergeControlToEnd(jsgraph(), ret); | |
2916 } | 2913 } |
2917 | 2914 |
2918 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { | 2915 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { |
2919 DCHECK(module_ && module_->instance); | 2916 DCHECK(module_ && module_->instance); |
2920 if (offset == 0) { | 2917 if (offset == 0) { |
2921 if (!mem_buffer_) { | 2918 if (!mem_buffer_) { |
2922 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( | 2919 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( |
2923 reinterpret_cast<uintptr_t>(module_->instance->mem_start), | 2920 reinterpret_cast<uintptr_t>(module_->instance->mem_start), |
2924 RelocInfo::WASM_MEMORY_REFERENCE); | 2921 RelocInfo::WASM_MEMORY_REFERENCE); |
2925 } | 2922 } |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3693 Smi::FromInt(instruction.instr_offset)); | 3690 Smi::FromInt(instruction.instr_offset)); |
3694 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, | 3691 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, |
3695 Smi::FromInt(instruction.landing_offset)); | 3692 Smi::FromInt(instruction.landing_offset)); |
3696 } | 3693 } |
3697 return fn_protected; | 3694 return fn_protected; |
3698 } | 3695 } |
3699 | 3696 |
3700 } // namespace compiler | 3697 } // namespace compiler |
3701 } // namespace internal | 3698 } // namespace internal |
3702 } // namespace v8 | 3699 } // namespace v8 |
OLD | NEW |