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 "src/isolate-inl.h" | 7 #include "src/isolate-inl.h" |
8 | 8 |
9 #include "src/base/platform/elapsed-timer.h" | 9 #include "src/base/platform/elapsed-timer.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 2475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2486 graph()->NewNode(jsgraph()->machine()->Word32Sar(), | 2486 graph()->NewNode(jsgraph()->machine()->Word32Sar(), |
2487 val, jsgraph()->Int32Constant(31)), | 2487 val, jsgraph()->Int32Constant(31)), |
2488 call, start); | 2488 call, start); |
2489 } else { | 2489 } else { |
2490 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start); | 2490 ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start); |
2491 } | 2491 } |
2492 | 2492 |
2493 MergeControlToEnd(jsgraph(), ret); | 2493 MergeControlToEnd(jsgraph(), ret); |
2494 } | 2494 } |
2495 | 2495 |
| 2496 void WasmGraphBuilder::BuildWasmToInterpreter(uint32_t function_index, |
| 2497 wasm::FunctionSig* sig, |
| 2498 Handle<JSObject> wasm_obj) { |
| 2499 int wasm_count = static_cast<int>(sig->parameter_count()); |
| 2500 int param_count = jsgraph()->machine()->Is64() |
| 2501 ? wasm_count |
| 2502 : Int64Lowering::GetParameterCountAfterLowering(sig); |
| 2503 |
| 2504 // Build the start and the parameter nodes. |
| 2505 Node* start = Start(param_count + 3); |
| 2506 *effect_ = start; |
| 2507 *control_ = start; |
| 2508 |
| 2509 auto build_runtime_call = [&](Runtime::FunctionId f) -> Node* { |
| 2510 const Runtime::Function* fun = Runtime::FunctionForId(f); |
| 2511 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
| 2512 jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties, |
| 2513 CallDescriptor::kNoFlags); |
| 2514 DCHECK_EQ(1, fun->result_size); |
| 2515 DCHECK_EQ(2, fun->nargs); |
| 2516 Node* inputs[] = { |
| 2517 jsgraph()->CEntryStubConstant(fun->result_size), // C entry |
| 2518 jsgraph()->SmiConstant(function_index), // function index |
| 2519 jsgraph()->HeapConstant(wasm_obj), // wasm object |
| 2520 jsgraph()->ExternalConstant( |
| 2521 ExternalReference(f, jsgraph()->isolate())), // ref |
| 2522 jsgraph()->Int32Constant(fun->nargs), // arity |
| 2523 HeapConstant(jsgraph()->isolate()->native_context()), // context |
| 2524 *effect_, |
| 2525 *control_}; |
| 2526 Node* call = *control_ = *effect_ = |
| 2527 graph()->NewNode(jsgraph()->common()->Call(desc), |
| 2528 static_cast<int>(arraysize(inputs)), inputs); |
| 2529 *control_ = call; |
| 2530 *effect_ = call; |
| 2531 return call; |
| 2532 }; |
| 2533 |
| 2534 // Get a buffer to store all parameters. |
| 2535 Node* arg_buffer = build_runtime_call(Runtime::kGetWasmInterpreterBuffer); |
| 2536 |
| 2537 // Now store all our parameters to the buffer. |
| 2538 int param_index = 0; |
| 2539 int offset = 0; |
| 2540 for (int i = 0; i < wasm_count; i++) { |
| 2541 Node* param = |
| 2542 graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start); |
| 2543 bool is_lower_half_i64 = |
| 2544 jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64; |
| 2545 MachineRepresentation param_rep = |
| 2546 is_lower_half_i64 ? wasm::kAstI32 : sig->GetParam(i); |
| 2547 StoreRepresentation store_rep(param_rep, WriteBarrierKind::kNoWriteBarrier); |
| 2548 *effect_ = |
| 2549 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer, |
| 2550 Int32Constant(offset), param, *effect_, *control_); |
| 2551 offset += 1 << ElementSizeLog2Of(param_rep); |
| 2552 if (is_lower_half_i64) { |
| 2553 // Also store the upper half. |
| 2554 param = graph()->NewNode(jsgraph()->common()->Parameter(param_index++), |
| 2555 start); |
| 2556 StoreRepresentation store_rep(wasm::kAstI32, |
| 2557 WriteBarrierKind::kNoWriteBarrier); |
| 2558 *effect_ = |
| 2559 graph()->NewNode(jsgraph()->machine()->Store(store_rep), arg_buffer, |
| 2560 Int32Constant(offset), param, *effect_, *control_); |
| 2561 offset += 1 << ElementSizeLog2Of(wasm::kAstI32); |
| 2562 } |
| 2563 } |
| 2564 DCHECK_EQ(param_count, param_index); |
| 2565 |
| 2566 build_runtime_call(Runtime::kWasmRunInterpreter); |
| 2567 |
| 2568 // Convert the return value back. |
| 2569 Node* ret; |
| 2570 if (jsgraph()->machine()->Is32() && sig->return_count() > 0 && |
| 2571 sig->GetReturn() == wasm::kAstI64) { |
| 2572 LoadRepresentation load_rep(wasm::kAstI32, MachineSemantic::kNone); |
| 2573 Node* lower = |
| 2574 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, |
| 2575 Int32Constant(0), *effect_, *control_); |
| 2576 Node* upper = |
| 2577 graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, |
| 2578 Int32Constant(4), *effect_, *control_); |
| 2579 ret = graph()->NewNode(jsgraph()->common()->Return(), upper, lower, |
| 2580 *effect_, *control_); |
| 2581 } else { |
| 2582 Node* val; |
| 2583 if (sig->return_count() == 0) { |
| 2584 val = Int32Constant(0); |
| 2585 } else { |
| 2586 LoadRepresentation load_rep(sig->GetReturn(), MachineSemantic::kNone); |
| 2587 val = graph()->NewNode(jsgraph()->machine()->Load(load_rep), arg_buffer, |
| 2588 Int32Constant(0), *effect_, *control_); |
| 2589 } |
| 2590 ret = graph()->NewNode(jsgraph()->common()->Return(), val, *effect_, |
| 2591 *control_); |
| 2592 } |
| 2593 |
| 2594 MergeControlToEnd(jsgraph(), ret); |
| 2595 } |
| 2596 |
2496 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { | 2597 Node* WasmGraphBuilder::MemBuffer(uint32_t offset) { |
2497 DCHECK(module_ && module_->instance); | 2598 DCHECK(module_ && module_->instance); |
2498 if (offset == 0) { | 2599 if (offset == 0) { |
2499 if (!mem_buffer_) { | 2600 if (!mem_buffer_) { |
2500 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( | 2601 mem_buffer_ = jsgraph()->RelocatableIntPtrConstant( |
2501 reinterpret_cast<uintptr_t>(module_->instance->mem_start), | 2602 reinterpret_cast<uintptr_t>(module_->instance->mem_start), |
2502 RelocInfo::WASM_MEMORY_REFERENCE); | 2603 RelocInfo::WASM_MEMORY_REFERENCE); |
2503 } | 2604 } |
2504 return mem_buffer_; | 2605 return mem_buffer_; |
2505 } else { | 2606 } else { |
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3092 if (debugging) { | 3193 if (debugging) { |
3093 buffer.Dispose(); | 3194 buffer.Dispose(); |
3094 } | 3195 } |
3095 | 3196 |
3096 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info, | 3197 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info, |
3097 "wasm-to-js", 0, module_name); | 3198 "wasm-to-js", 0, module_name); |
3098 } | 3199 } |
3099 return code; | 3200 return code; |
3100 } | 3201 } |
3101 | 3202 |
| 3203 Handle<Code> CompileWasmToInterpreter(Isolate* isolate, uint32_t func_index, |
| 3204 wasm::FunctionSig* sig, |
| 3205 Handle<JSObject> wasm_obj) { |
| 3206 //---------------------------------------------------------------------------- |
| 3207 // Create the Graph |
| 3208 //---------------------------------------------------------------------------- |
| 3209 Zone zone(isolate->allocator()); |
| 3210 Graph graph(&zone); |
| 3211 CommonOperatorBuilder common(&zone); |
| 3212 MachineOperatorBuilder machine(&zone); |
| 3213 JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine); |
| 3214 |
| 3215 Node* control = nullptr; |
| 3216 Node* effect = nullptr; |
| 3217 |
| 3218 WasmGraphBuilder builder(&zone, &jsgraph, sig); |
| 3219 builder.set_control_ptr(&control); |
| 3220 builder.set_effect_ptr(&effect); |
| 3221 builder.BuildWasmToInterpreter(func_index, sig, wasm_obj); |
| 3222 |
| 3223 Handle<Code> code = Handle<Code>::null(); |
| 3224 { |
| 3225 if (FLAG_trace_turbo_graph) { // Simple textual RPO. |
| 3226 OFStream os(stdout); |
| 3227 os << "-- Wasm to interpreter graph -- " << std::endl; |
| 3228 os << AsRPO(graph); |
| 3229 } |
| 3230 |
| 3231 // Schedule and compile to machine code. |
| 3232 CallDescriptor* incoming = |
| 3233 wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig); |
| 3234 if (machine.Is32()) { |
| 3235 incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming); |
| 3236 } |
| 3237 Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_INTERPRETER); |
| 3238 char buf[32]; |
| 3239 int buf_len = |
| 3240 SNPrintF(ArrayVector(buf), "wasm-to-interpreter#%d", func_index); |
| 3241 DCHECK(buf_len > 0 && buf_len < sizeof(buf)); |
| 3242 Vector<const char> debug_name(buf, buf_len); |
| 3243 |
| 3244 CompilationInfo info(debug_name, isolate, &zone, flags); |
| 3245 code = Pipeline::GenerateCodeForTesting(&info, incoming, &graph, nullptr); |
| 3246 #ifdef ENABLE_DISASSEMBLER |
| 3247 if (FLAG_print_opt_code && !code.is_null()) { |
| 3248 OFStream os(stdout); |
| 3249 code->Disassemble(buf, os); |
| 3250 } |
| 3251 #endif |
| 3252 |
| 3253 RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, &info, buf, |
| 3254 func_index, debug_name); |
| 3255 } |
| 3256 |
| 3257 Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(1); |
| 3258 deopt_data->set(0, *wasm_obj); |
| 3259 code->set_deoptimization_data(*deopt_data); |
| 3260 |
| 3261 return code; |
| 3262 } |
| 3263 |
3102 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( | 3264 SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction( |
3103 double* decode_ms) { | 3265 double* decode_ms) { |
3104 base::ElapsedTimer decode_timer; | 3266 base::ElapsedTimer decode_timer; |
3105 if (FLAG_trace_wasm_decode_time) { | 3267 if (FLAG_trace_wasm_decode_time) { |
3106 decode_timer.Start(); | 3268 decode_timer.Start(); |
3107 } | 3269 } |
3108 // Create a TF graph during decoding. | 3270 // Create a TF graph during decoding. |
3109 | 3271 |
3110 Graph* graph = jsgraph_->graph(); | 3272 Graph* graph = jsgraph_->graph(); |
3111 CommonOperatorBuilder* common = jsgraph_->common(); | 3273 CommonOperatorBuilder* common = jsgraph_->common(); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3271 function_->code_start_offset), | 3433 function_->code_start_offset), |
3272 compile_ms); | 3434 compile_ms); |
3273 } | 3435 } |
3274 | 3436 |
3275 return code; | 3437 return code; |
3276 } | 3438 } |
3277 | 3439 |
3278 } // namespace compiler | 3440 } // namespace compiler |
3279 } // namespace internal | 3441 } // namespace internal |
3280 } // namespace v8 | 3442 } // namespace v8 |
OLD | NEW |