Chromium Code Reviews| 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 18 matching lines...) Expand all Loading... | |
| 29 #include "src/compiler/zone-stats.h" | 29 #include "src/compiler/zone-stats.h" |
| 30 | 30 |
| 31 #include "src/code-factory.h" | 31 #include "src/code-factory.h" |
| 32 #include "src/code-stubs.h" | 32 #include "src/code-stubs.h" |
| 33 #include "src/factory.h" | 33 #include "src/factory.h" |
| 34 #include "src/log-inl.h" | 34 #include "src/log-inl.h" |
| 35 | 35 |
| 36 #include "src/wasm/function-body-decoder.h" | 36 #include "src/wasm/function-body-decoder.h" |
| 37 #include "src/wasm/wasm-limits.h" | 37 #include "src/wasm/wasm-limits.h" |
| 38 #include "src/wasm/wasm-module.h" | 38 #include "src/wasm/wasm-module.h" |
| 39 #include "src/wasm/wasm-objects.h" | |
| 39 #include "src/wasm/wasm-opcodes.h" | 40 #include "src/wasm/wasm-opcodes.h" |
| 40 #include "src/wasm/wasm-text.h" | 41 #include "src/wasm/wasm-text.h" |
| 41 | 42 |
| 42 // TODO(titzer): pull WASM_64 up to a common header. | 43 // TODO(titzer): pull WASM_64 up to a common header. |
| 43 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 | 44 #if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64 |
| 44 #define WASM_64 1 | 45 #define WASM_64 1 |
| 45 #else | 46 #else |
| 46 #define WASM_64 0 | 47 #define WASM_64 0 |
| 47 #endif | 48 #endif |
| 48 | 49 |
| (...skipping 2855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2904 | 2905 |
| 2905 // Convert the return value back. | 2906 // Convert the return value back. |
| 2906 Node* i32_zero = jsgraph()->Int32Constant(0); | 2907 Node* i32_zero = jsgraph()->Int32Constant(0); |
| 2907 Node* val = sig->return_count() == 0 | 2908 Node* val = sig->return_count() == 0 |
| 2908 ? i32_zero | 2909 ? i32_zero |
| 2909 : FromJS(call, HeapConstant(isolate->native_context()), | 2910 : FromJS(call, HeapConstant(isolate->native_context()), |
| 2910 sig->GetReturn()); | 2911 sig->GetReturn()); |
| 2911 Return(val); | 2912 Return(val); |
| 2912 } | 2913 } |
| 2913 | 2914 |
| 2915 void WasmGraphBuilder::BuildWasmToInterpreter( | |
| 2916 uint32_t function_index, wasm::FunctionSig* sig, | |
| 2917 Handle<WasmInstanceObject> instance) { | |
| 2918 int wasm_count = static_cast<int>(sig->parameter_count()); | |
| 2919 int param_count = jsgraph()->machine()->Is64() | |
| 2920 ? wasm_count | |
| 2921 : Int64Lowering::GetParameterCountAfterLowering(sig); | |
| 2922 | |
| 2923 // Build the start and the parameter nodes. | |
| 2924 Node* start = Start(param_count + 3); | |
| 2925 *effect_ = start; | |
| 2926 *control_ = start; | |
| 2927 | |
| 2928 auto build_runtime_call = [&](Runtime::FunctionId f) -> Node* { | |
| 2929 Node* parameters[] = { | |
| 2930 jsgraph()->SmiConstant(function_index), // function index | |
| 2931 jsgraph()->HeapConstant(instance), // wasm instance | |
| 2932 }; | |
| 2933 return BuildCallToRuntime( | |
| 2934 f, jsgraph(), jsgraph()->isolate()->native_context(), parameters, | |
| 2935 arraysize(parameters), effect_, *control_); | |
| 2936 }; | |
| 2937 | |
| 2938 // Get a buffer to store all parameters. | |
| 2939 Node* arg_buffer = build_runtime_call(Runtime::kGetWasmInterpreterBuffer); | |
|
titzer
2017/01/10 19:00:51
I think we can put this buffer into the stack fram
titzer
2017/01/10 19:02:47
Actually, now that I think about it, we might be a
Clemens Hammacher
2017/01/11 15:05:29
Done: http://crrev.com/2624183002
Using a special
| |
| 2940 | |
| 2941 // Now store all our parameters to the buffer. | |
| 2942 int param_index = 0; | |
| 2943 int offset = 0; | |
| 2944 for (int i = 0; i < wasm_count; i++) { | |
| 2945 Node* param = Param(param_index++); | |
| 2946 bool is_i64_as_two_params = | |
| 2947 jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kWasmI64; | |
| 2948 MachineRepresentation param_rep = | |
| 2949 is_i64_as_two_params ? wasm::kWasmI32 : sig->GetParam(i); | |
| 2950 StoreRepresentation store_rep(param_rep, WriteBarrierKind::kNoWriteBarrier); | |
| 2951 *effect_ = | |
| 2952 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer, | |
| 2953 Int32Constant(offset), param, *effect_, *control_); | |
| 2954 offset += 1 << ElementSizeLog2Of(param_rep); | |
| 2955 if (is_i64_as_two_params) { | |
|
titzer
2017/01/10 19:00:51
I think this might be backward for big-endian plat
Clemens Hammacher
2017/01/11 15:05:29
According to AddParameterNodes (line 2811) and Bui
| |
| 2956 // Also store the upper half. | |
| 2957 param = Param(param_index++); | |
| 2958 StoreRepresentation store_rep(wasm::kWasmI32, | |
| 2959 WriteBarrierKind::kNoWriteBarrier); | |
| 2960 *effect_ = | |
| 2961 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer, | |
| 2962 Int32Constant(offset), param, *effect_, *control_); | |
| 2963 offset += 1 << ElementSizeLog2Of(wasm::kWasmI32); | |
|
titzer
2017/01/10 19:00:51
sizeof(int32_t) is also fine.
Clemens Hammacher
2017/01/11 15:05:29
Yes, but this way it is the same expression as 7 l
| |
| 2964 } | |
| 2965 } | |
| 2966 DCHECK_EQ(param_count, param_index); | |
| 2967 | |
| 2968 build_runtime_call(Runtime::kWasmRunInterpreter); | |
| 2969 | |
| 2970 // Read back the return value. | |
| 2971 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && | |
| 2972 sig->GetReturn() == wasm::kWasmI64) { | |
| 2973 MachineType load_rep = wasm::WasmOpcodes::MachineTypeFor(wasm::kWasmI32); | |
| 2974 Node* lower = | |
| 2975 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, | |
| 2976 Int32Constant(0), *effect_, *control_); | |
| 2977 Node* upper = | |
| 2978 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, | |
| 2979 Int32Constant(4), *effect_, *control_); | |
| 2980 Return(upper, lower); | |
| 2981 } else { | |
| 2982 Node* val; | |
| 2983 if (sig->return_count() == 0) { | |
| 2984 val = Int32Constant(0); | |
| 2985 } else { | |
| 2986 MachineType load_rep = | |
| 2987 wasm::WasmOpcodes::MachineTypeFor(sig->GetReturn()); | |
| 2988 val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, | |
| 2989 Int32Constant(0), *effect_, *control_); | |
| 2990 } | |
| 2991 Return(val); | |
| 2992 } | |
| 2993 } | |
| 2994 | |
| 2914 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { | 2995 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { |
| 2915 DCHECK(module_ && module_->instance); | 2996 DCHECK(module_ && module_->instance); |
| 2916 if (offset == 0) { | 2997 if (offset == 0) { |
| 2917 if (!mem_buffer_) { | 2998 if (!mem_buffer_) { |
| 2918 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( | 2999 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( |
| 2919 reinterpret_cast<uintptr_t>(module_->instance->mem_start), | 3000 reinterpret_cast<uintptr_t>(module_->instance->mem_start), |
| 2920 RelocInfo::WASM_MEMORY_REFERENCE); | 3001 RelocInfo::WASM_MEMORY_REFERENCE); |
| 2921 } | 3002 } |
| 2922 return mem_buffer_; | 3003 return mem_buffer_; |
| 2923 } else { | 3004 } else { |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3479 } | 3560 } |
| 3480 RecordFunctionCompilation( | 3561 RecordFunctionCompilation( |
| 3481 CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index, | 3562 CodeEventListener::FUNCTION_TAG, isolate, code, "wasm-to-js", index, |
| 3482 {module_name->ToCString().get(), module_name->length()}, | 3563 {module_name->ToCString().get(), module_name->length()}, |
| 3483 {function_name, function_name_size}); | 3564 {function_name, function_name_size}); |
| 3484 } | 3565 } |
| 3485 | 3566 |
| 3486 return code; | 3567 return code; |
| 3487 } | 3568 } |
| 3488 | 3569 |
| 3570 Handle<Code> CompileWasmToInterpreter(Isolate* isolate, uint32_t func_index, | |
| 3571 wasm::FunctionSig* sig, | |
| 3572 Handle<WasmInstanceObject> instance) { | |
| 3573 //---------------------------------------------------------------------------- | |
| 3574 // Create the Graph | |
| 3575 //---------------------------------------------------------------------------- | |
| 3576 Zone zone(isolate->allocator(), ZONE_NAME); | |
| 3577 Graph graph(&zone); | |
| 3578 CommonOperatorBuilder common(&zone); | |
| 3579 MachineOperatorBuilder machine(&zone); | |
| 3580 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); | |
| 3581 | |
| 3582 Node* control = nullptr; | |
| 3583 Node* effect = nullptr; | |
| 3584 | |
| 3585 WasmGraphBuilder builder(nullptr, &zone, &jsgraph, sig); | |
| 3586 builder.set_control_ptr(&control); | |
| 3587 builder.set_effect_ptr(&effect); | |
| 3588 builder.BuildWasmToInterpreter(func_index, sig, instance); | |
| 3589 | |
| 3590 Handle<Code> code = Handle<Code>::null(); | |
| 3591 { | |
| 3592 if (FLAG_trace_turbo_graph) { // Simple textual RPO. | |
| 3593 OFStream os(stdout); | |
| 3594 os << "-- Wasm to interpreter graph -- " << std::endl; | |
| 3595 os << AsRPO(graph); | |
| 3596 } | |
| 3597 | |
| 3598 // Schedule and compile to machine code. | |
| 3599 CallDescriptor* incoming = | |
| 3600 wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig); | |
| 3601 if (machine.Is32()) { | |
| 3602 incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming); | |
| 3603 } | |
| 3604 Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_INTERPRETER); | |
| 3605 EmbeddedVector<char, 32> debug_name; | |
| 3606 int name_len = SNPrintF(debug_name, "wasm-to-interpreter#%d", func_index); | |
| 3607 DCHECK(name_len > 0 && name_len < debug_name.length()); | |
| 3608 debug_name.Truncate(name_len); | |
| 3609 DCHECK_EQ('\0', debug_name.start()[debug_name.length()]); | |
| 3610 | |
| 3611 CompilationInfo info(debug_name, isolate, &zone, flags); | |
| 3612 code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); | |
| 3613 #ifdef ENABLE_DISASSEMBLER | |
| 3614 if (FLAG_print_opt_code && !code.is_null()) { | |
| 3615 OFStream os(stdout); | |
| 3616 code->Disassemble(debug_name.start(), os); | |
| 3617 } | |
| 3618 #endif | |
| 3619 | |
| 3620 if (isolate->logger()->is_logging_code_events() || | |
| 3621 isolate->is_profiling()) { | |
| 3622 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, isolate, code, | |
| 3623 "wasm-to-interpreter", func_index, | |
| 3624 wasm::WasmName("module"), debug_name); | |
| 3625 } | |
| 3626 } | |
| 3627 | |
| 3628 Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1, TENURED); | |
| 3629 Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance); | |
| 3630 deopt_data->set(0, *weak_instance); | |
| 3631 code->set_deoptimization_data(*deopt_data); | |
| 3632 | |
| 3633 return code; | |
| 3634 } | |
| 3635 | |
| 3489 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( | 3636 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( |
| 3490 double* decode_ms) { | 3637 double* decode_ms) { |
| 3491 base::ElapsedTimer decode_timer; | 3638 base::ElapsedTimer decode_timer; |
| 3492 if (FLAG_trace_wasm_decode_time) { | 3639 if (FLAG_trace_wasm_decode_time) { |
| 3493 decode_timer.Start(); | 3640 decode_timer.Start(); |
| 3494 } | 3641 } |
| 3495 // Create a TF graph during decoding. | 3642 // Create a TF graph during decoding. |
| 3496 | 3643 |
| 3497 Graph* graph = jsgraph_->graph(); | 3644 Graph* graph = jsgraph_->graph(); |
| 3498 CommonOperatorBuilder* common = jsgraph_->common(); | 3645 CommonOperatorBuilder* common = jsgraph_->common(); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3686 Smi::FromInt(instruction.instr_offset)); | 3833 Smi::FromInt(instruction.instr_offset)); |
| 3687 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, | 3834 fn_protected->set(Code::kTrapDataSize * i + Code::kTrapLandingOffset, |
| 3688 Smi::FromInt(instruction.landing_offset)); | 3835 Smi::FromInt(instruction.landing_offset)); |
| 3689 } | 3836 } |
| 3690 return fn_protected; | 3837 return fn_protected; |
| 3691 } | 3838 } |
| 3692 | 3839 |
| 3693 } // namespace compiler | 3840 } // namespace compiler |
| 3694 } // namespace internal | 3841 } // namespace internal |
| 3695 } // namespace v8 | 3842 } // namespace v8 |
| OLD | NEW |