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 |