| 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 |