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 "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 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 Node* trap_reason_smi = builder_->BuildChangeInt32ToSmi(trap_reason_); | 226 Node* trap_reason_smi = builder_->BuildChangeInt32ToSmi(trap_reason_); |
| 227 Node* trap_position_smi = builder_->BuildChangeInt32ToSmi(trap_position_); | 227 Node* trap_position_smi = builder_->BuildChangeInt32ToSmi(trap_position_); |
| 228 | 228 |
| 229 if (module && !module->instance->context.is_null()) { | 229 if (module && !module->instance->context.is_null()) { |
| 230 // Use the module context to call the runtime to throw an exception. | 230 // Use the module context to call the runtime to throw an exception. |
| 231 Runtime::FunctionId f = Runtime::kThrowWasmError; | 231 Runtime::FunctionId f = Runtime::kThrowWasmError; |
| 232 const Runtime::Function* fun = Runtime::FunctionForId(f); | 232 const Runtime::Function* fun = Runtime::FunctionForId(f); |
| 233 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( | 233 CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor( |
| 234 jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties, | 234 jsgraph()->zone(), f, fun->nargs, Operator::kNoProperties, |
| 235 CallDescriptor::kNoFlags); | 235 CallDescriptor::kNoFlags); |
| 236 // CEntryStubConstant nodes have to be created and cached in the main | |
| 237 // thread. At the moment this is only done for CEntryStubConstant(1). | |
| 238 DCHECK_EQ(1, fun->result_size); | |
| 236 Node* inputs[] = { | 239 Node* inputs[] = { |
| 237 jsgraph()->CEntryStubConstant(fun->result_size), // C entry | 240 jsgraph()->CEntryStubConstant(fun->result_size), // C entry |
| 238 trap_reason_smi, // message id | 241 trap_reason_smi, // message id |
| 239 trap_position_smi, // byte position | 242 trap_position_smi, // byte position |
| 240 jsgraph()->ExternalConstant( | 243 jsgraph()->ExternalConstant( // ref |
| 241 ExternalReference(f, jsgraph()->isolate())), // ref | 244 ExternalReference(f, jsgraph()->isolate())), |
| 242 jsgraph()->Int32Constant(fun->nargs), // arity | 245 jsgraph()->Int32Constant(fun->nargs), // arity |
| 243 jsgraph()->Constant(module->instance->context), // context | 246 graph()->NewNode(jsgraph()->common()->HeapConstant( // context |
| 244 *effect_ptr, | 247 Handle<HeapObject>::cast(module->instance->context))), |
| 245 *control_ptr}; | 248 *effect_ptr, *control_ptr}; |
| 246 | 249 |
| 247 Node* node = graph()->NewNode( | 250 Node* node = graph()->NewNode( |
| 248 common()->Call(desc), static_cast<int>(arraysize(inputs)), inputs); | 251 common()->Call(desc), static_cast<int>(arraysize(inputs)), inputs); |
| 249 *control_ptr = node; | 252 *control_ptr = node; |
| 250 *effect_ptr = node; | 253 *effect_ptr = node; |
| 251 } | 254 } |
| 252 if (false) { | 255 if (false) { |
| 253 // End the control flow with a throw | 256 // End the control flow with a throw |
| 254 Node* thrw = | 257 Node* thrw = |
| 255 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), | 258 graph()->NewNode(common()->Throw(), jsgraph()->ZeroConstant(), |
| (...skipping 1615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1871 | 1874 |
| 1872 *effect_ = call; | 1875 *effect_ = call; |
| 1873 return call; | 1876 return call; |
| 1874 } | 1877 } |
| 1875 | 1878 |
| 1876 Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, | 1879 Node* WasmGraphBuilder::CallDirect(uint32_t index, Node** args, |
| 1877 wasm::WasmCodePosition position) { | 1880 wasm::WasmCodePosition position) { |
| 1878 DCHECK_NULL(args[0]); | 1881 DCHECK_NULL(args[0]); |
| 1879 | 1882 |
| 1880 // Add code object as constant. | 1883 // Add code object as constant. |
| 1881 args[0] = Constant(module_->GetFunctionCode(index)); | 1884 args[0] = graph()->NewNode(jsgraph()->common()->HeapConstant( |
| 1885 Handle<HeapObject>::cast(module_->GetFunctionCode(index)))); | |
|
Michael Starzinger
2016/05/10 09:06:46
nit: Why is this up-cast necessary? Isn't GetFunct
ahaas
2016/05/10 09:45:48
I removed the up-casts. Thanks
| |
| 1882 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); | 1886 wasm::FunctionSig* sig = module_->GetFunctionSignature(index); |
| 1883 | 1887 |
| 1884 return BuildWasmCall(sig, args, position); | 1888 return BuildWasmCall(sig, args, position); |
| 1885 } | 1889 } |
| 1886 | 1890 |
| 1887 Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args, | 1891 Node* WasmGraphBuilder::CallImport(uint32_t index, Node** args, |
| 1888 wasm::WasmCodePosition position) { | 1892 wasm::WasmCodePosition position) { |
| 1889 DCHECK_NULL(args[0]); | 1893 DCHECK_NULL(args[0]); |
| 1890 | 1894 |
| 1891 // Add code object as constant. | 1895 // Add code object as constant. |
| 1892 args[0] = Constant(module_->GetImportCode(index)); | 1896 args[0] = graph()->NewNode(jsgraph()->common()->HeapConstant( |
| 1897 Handle<HeapObject>::cast(module_->GetImportCode(index)))); | |
| 1893 wasm::FunctionSig* sig = module_->GetImportSignature(index); | 1898 wasm::FunctionSig* sig = module_->GetImportSignature(index); |
| 1894 | 1899 |
| 1895 return BuildWasmCall(sig, args, position); | 1900 return BuildWasmCall(sig, args, position); |
| 1896 } | 1901 } |
| 1897 | 1902 |
| 1898 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, | 1903 Node* WasmGraphBuilder::CallIndirect(uint32_t index, Node** args, |
| 1899 wasm::WasmCodePosition position) { | 1904 wasm::WasmCodePosition position) { |
| 1900 DCHECK_NOT_NULL(args[0]); | 1905 DCHECK_NOT_NULL(args[0]); |
| 1901 DCHECK(module_ && module_->instance); | 1906 DCHECK(module_ && module_->instance); |
| 1902 | 1907 |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2527 } else { | 2532 } else { |
| 2528 return jsgraph()->Int32Constant(size + offset); | 2533 return jsgraph()->Int32Constant(size + offset); |
| 2529 } | 2534 } |
| 2530 } | 2535 } |
| 2531 | 2536 |
| 2532 | 2537 |
| 2533 Node* WasmGraphBuilder::FunctionTable() { | 2538 Node* WasmGraphBuilder::FunctionTable() { |
| 2534 DCHECK(module_ && module_->instance && | 2539 DCHECK(module_ && module_->instance && |
| 2535 !module_->instance->function_table.is_null()); | 2540 !module_->instance->function_table.is_null()); |
| 2536 if (!function_table_) { | 2541 if (!function_table_) { |
| 2537 function_table_ = jsgraph()->Constant(module_->instance->function_table); | 2542 function_table_ = graph()->NewNode(jsgraph()->common()->HeapConstant( |
| 2543 Handle<HeapObject>::cast(module_->instance->function_table))); | |
| 2538 } | 2544 } |
| 2539 return function_table_; | 2545 return function_table_; |
| 2540 } | 2546 } |
| 2541 | 2547 |
| 2542 | 2548 |
| 2543 Node* WasmGraphBuilder::LoadGlobal(uint32_t index) { | 2549 Node* WasmGraphBuilder::LoadGlobal(uint32_t index) { |
| 2544 DCHECK(module_ && module_->instance && module_->instance->globals_start); | 2550 DCHECK(module_ && module_->instance && module_->instance->globals_start); |
| 2545 MachineType mem_type = module_->GetGlobalType(index); | 2551 MachineType mem_type = module_->GetGlobalType(index); |
| 2546 Node* addr = jsgraph()->IntPtrConstant( | 2552 Node* addr = jsgraph()->IntPtrConstant( |
| 2547 reinterpret_cast<uintptr_t>(module_->instance->globals_start + | 2553 reinterpret_cast<uintptr_t>(module_->instance->globals_start + |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2869 buffer.Dispose(); | 2875 buffer.Dispose(); |
| 2870 } | 2876 } |
| 2871 | 2877 |
| 2872 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0, | 2878 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0, |
| 2873 module_name); | 2879 module_name); |
| 2874 } | 2880 } |
| 2875 return code; | 2881 return code; |
| 2876 } | 2882 } |
| 2877 | 2883 |
| 2878 std::pair<JSGraph*, SourcePositionTable*> BuildGraphForWasmFunction( | 2884 std::pair<JSGraph*, SourcePositionTable*> BuildGraphForWasmFunction( |
| 2879 Zone* zone, wasm::ErrorThrower* thrower, Isolate* isolate, | 2885 JSGraph* jsgraph, wasm::ErrorThrower* thrower, Isolate* isolate, |
| 2880 wasm::ModuleEnv*& module_env, const wasm::WasmFunction* function, | 2886 wasm::ModuleEnv*& module_env, const wasm::WasmFunction* function, |
| 2881 double* decode_ms) { | 2887 double* decode_ms) { |
| 2882 base::ElapsedTimer decode_timer; | 2888 base::ElapsedTimer decode_timer; |
| 2883 if (FLAG_trace_wasm_decode_time) { | 2889 if (FLAG_trace_wasm_decode_time) { |
| 2884 decode_timer.Start(); | 2890 decode_timer.Start(); |
| 2885 } | 2891 } |
| 2886 // Create a TF graph during decoding. | 2892 // Create a TF graph during decoding. |
| 2887 Graph* graph = new (zone) Graph(zone); | 2893 Graph* graph = jsgraph->graph(); |
| 2888 CommonOperatorBuilder* common = new (zone) CommonOperatorBuilder(zone); | 2894 CommonOperatorBuilder* common = jsgraph->common(); |
| 2889 MachineOperatorBuilder* machine = new (zone) MachineOperatorBuilder( | 2895 MachineOperatorBuilder* machine = jsgraph->machine(); |
| 2890 zone, MachineType::PointerRepresentation(), | |
| 2891 InstructionSelector::SupportedMachineOperatorFlags()); | |
| 2892 JSGraph* jsgraph = | |
| 2893 new (zone) JSGraph(isolate, graph, common, nullptr, nullptr, machine); | |
| 2894 SourcePositionTable* source_position_table = | 2896 SourcePositionTable* source_position_table = |
| 2895 new (zone) SourcePositionTable(graph); | 2897 new (jsgraph->zone()) SourcePositionTable(graph); |
| 2896 WasmGraphBuilder builder(zone, jsgraph, function->sig, source_position_table); | 2898 WasmGraphBuilder builder(jsgraph->zone(), jsgraph, function->sig, |
| 2899 source_position_table); | |
| 2897 wasm::FunctionBody body = { | 2900 wasm::FunctionBody body = { |
| 2898 module_env, function->sig, module_env->module->module_start, | 2901 module_env, function->sig, module_env->module->module_start, |
| 2899 module_env->module->module_start + function->code_start_offset, | 2902 module_env->module->module_start + function->code_start_offset, |
| 2900 module_env->module->module_start + function->code_end_offset}; | 2903 module_env->module->module_start + function->code_end_offset}; |
| 2901 wasm::TreeResult result = | 2904 wasm::TreeResult result = |
| 2902 wasm::BuildTFGraph(isolate->allocator(), &builder, body); | 2905 wasm::BuildTFGraph(isolate->allocator(), &builder, body); |
| 2903 | 2906 |
| 2904 if (machine->Is32()) { | 2907 if (machine->Is32()) { |
| 2905 Int64Lowering r(graph, machine, common, zone, function->sig); | 2908 Int64Lowering r(graph, machine, common, jsgraph->zone(), function->sig); |
| 2906 r.LowerGraph(); | 2909 r.LowerGraph(); |
| 2907 } | 2910 } |
| 2908 | 2911 |
| 2909 if (result.failed()) { | 2912 if (result.failed()) { |
| 2910 if (FLAG_trace_wasm_compiler) { | 2913 if (FLAG_trace_wasm_compiler) { |
| 2911 OFStream os(stdout); | 2914 OFStream os(stdout); |
| 2912 os << "Compilation failed: " << result << std::endl; | 2915 os << "Compilation failed: " << result << std::endl; |
| 2913 } | 2916 } |
| 2914 // Add the function as another context for the exception | 2917 // Add the function as another context for the exception |
| 2915 ScopedVector<char> buffer(128); | 2918 ScopedVector<char> buffer(128); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2932 | 2935 |
| 2933 class WasmCompilationUnit { | 2936 class WasmCompilationUnit { |
| 2934 public: | 2937 public: |
| 2935 WasmCompilationUnit(wasm::ErrorThrower* thrower, Isolate* isolate, | 2938 WasmCompilationUnit(wasm::ErrorThrower* thrower, Isolate* isolate, |
| 2936 wasm::ModuleEnv* module_env, | 2939 wasm::ModuleEnv* module_env, |
| 2937 const wasm::WasmFunction* function, uint32_t index) | 2940 const wasm::WasmFunction* function, uint32_t index) |
| 2938 : thrower_(thrower), | 2941 : thrower_(thrower), |
| 2939 isolate_(isolate), | 2942 isolate_(isolate), |
| 2940 module_env_(module_env), | 2943 module_env_(module_env), |
| 2941 function_(function), | 2944 function_(function), |
| 2945 graph_zone_(new Zone(isolate->allocator())), | |
| 2946 jsgraph_(new (graph_zone()) JSGraph( | |
| 2947 isolate, new (graph_zone()) Graph(graph_zone()), | |
| 2948 new (graph_zone()) CommonOperatorBuilder(graph_zone()), nullptr, | |
| 2949 nullptr, | |
| 2950 new (graph_zone()) MachineOperatorBuilder( | |
| 2951 graph_zone(), MachineType::PointerRepresentation(), | |
| 2952 InstructionSelector::SupportedMachineOperatorFlags()))), | |
| 2942 compilation_zone_(isolate->allocator()), | 2953 compilation_zone_(isolate->allocator()), |
| 2943 info_(function->name_length != 0 | 2954 info_(function->name_length != 0 |
| 2944 ? module_env->module->GetNameOrNull(function->name_offset, | 2955 ? module_env->module->GetNameOrNull(function->name_offset, |
| 2945 function->name_length) | 2956 function->name_length) |
| 2946 : ArrayVector("wasm"), | 2957 : ArrayVector("wasm"), |
| 2947 isolate, &compilation_zone_, | 2958 isolate, &compilation_zone_, |
| 2948 Code::ComputeFlags(Code::WASM_FUNCTION)), | 2959 Code::ComputeFlags(Code::WASM_FUNCTION)), |
| 2949 job_(), | 2960 job_(), |
| 2950 index_(index), | 2961 index_(index), |
| 2951 ok_(true) {} | 2962 ok_(true) { |
| 2963 // Create and cache this node in the main thread. | |
| 2964 jsgraph_->CEntryStubConstant(1); | |
| 2965 } | |
| 2966 | |
| 2967 Zone* graph_zone() { return graph_zone_.get(); } | |
| 2952 | 2968 |
| 2953 void ExecuteCompilation() { | 2969 void ExecuteCompilation() { |
| 2954 HistogramTimerScope wasm_compile_function_time_scope( | 2970 HistogramTimerScope wasm_compile_function_time_scope( |
| 2955 isolate_->counters()->wasm_compile_function_time()); | 2971 isolate_->counters()->wasm_compile_function_time()); |
| 2956 if (FLAG_trace_wasm_compiler) { | 2972 if (FLAG_trace_wasm_compiler) { |
| 2957 OFStream os(stdout); | 2973 OFStream os(stdout); |
| 2958 os << "Compiling WASM function " | 2974 os << "Compiling WASM function " |
| 2959 << wasm::WasmFunctionName(function_, module_env_) << std::endl; | 2975 << wasm::WasmFunctionName(function_, module_env_) << std::endl; |
| 2960 os << std::endl; | 2976 os << std::endl; |
| 2961 } | 2977 } |
| 2962 | 2978 |
| 2963 double decode_ms = 0; | 2979 double decode_ms = 0; |
| 2964 size_t node_count = 0; | 2980 size_t node_count = 0; |
| 2965 | 2981 |
| 2966 Zone zone(isolate_->allocator()); | 2982 base::SmartPointer<Zone> graph_zone(graph_zone_.Detach()); |
| 2967 std::pair<JSGraph*, SourcePositionTable*> graph_result = | 2983 std::pair<JSGraph*, SourcePositionTable*> graph_result = |
| 2968 BuildGraphForWasmFunction(&zone, thrower_, isolate_, module_env_, | 2984 BuildGraphForWasmFunction(jsgraph_, thrower_, isolate_, module_env_, |
| 2969 function_, &decode_ms); | 2985 function_, &decode_ms); |
| 2970 JSGraph* jsgraph = graph_result.first; | 2986 JSGraph* jsgraph = graph_result.first; |
| 2971 SourcePositionTable* source_positions = graph_result.second; | 2987 SourcePositionTable* source_positions = graph_result.second; |
| 2972 | 2988 |
| 2973 if (jsgraph == nullptr) { | 2989 if (jsgraph == nullptr) { |
| 2974 ok_ = false; | 2990 ok_ = false; |
| 2975 return; | 2991 return; |
| 2976 } | 2992 } |
| 2977 | 2993 |
| 2978 base::ElapsedTimer pipeline_timer; | 2994 base::ElapsedTimer pipeline_timer; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3043 compile_ms); | 3059 compile_ms); |
| 3044 } | 3060 } |
| 3045 | 3061 |
| 3046 return code; | 3062 return code; |
| 3047 } | 3063 } |
| 3048 | 3064 |
| 3049 wasm::ErrorThrower* thrower_; | 3065 wasm::ErrorThrower* thrower_; |
| 3050 Isolate* isolate_; | 3066 Isolate* isolate_; |
| 3051 wasm::ModuleEnv* module_env_; | 3067 wasm::ModuleEnv* module_env_; |
| 3052 const wasm::WasmFunction* function_; | 3068 const wasm::WasmFunction* function_; |
| 3069 // The graph zone is deallocated at the end of ExecuteCompilation. | |
| 3070 base::SmartPointer<Zone> graph_zone_; | |
| 3071 JSGraph* jsgraph_; | |
| 3053 Zone compilation_zone_; | 3072 Zone compilation_zone_; |
| 3054 CompilationInfo info_; | 3073 CompilationInfo info_; |
| 3055 base::SmartPointer<CompilationJob> job_; | 3074 base::SmartPointer<CompilationJob> job_; |
| 3056 uint32_t index_; | 3075 uint32_t index_; |
| 3057 bool ok_; | 3076 bool ok_; |
| 3058 }; | 3077 }; |
| 3059 | 3078 |
| 3060 WasmCompilationUnit* CreateWasmCompilationUnit( | 3079 WasmCompilationUnit* CreateWasmCompilationUnit( |
| 3061 wasm::ErrorThrower* thrower, Isolate* isolate, wasm::ModuleEnv* module_env, | 3080 wasm::ErrorThrower* thrower, Isolate* isolate, wasm::ModuleEnv* module_env, |
| 3062 const wasm::WasmFunction* function, uint32_t index) { | 3081 const wasm::WasmFunction* function, uint32_t index) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 3083 const wasm::WasmFunction* function) { | 3102 const wasm::WasmFunction* function) { |
| 3084 WasmCompilationUnit* unit = | 3103 WasmCompilationUnit* unit = |
| 3085 CreateWasmCompilationUnit(thrower, isolate, module_env, function, 0); | 3104 CreateWasmCompilationUnit(thrower, isolate, module_env, function, 0); |
| 3086 ExecuteCompilation(unit); | 3105 ExecuteCompilation(unit); |
| 3087 return FinishCompilation(unit); | 3106 return FinishCompilation(unit); |
| 3088 } | 3107 } |
| 3089 | 3108 |
| 3090 } // namespace compiler | 3109 } // namespace compiler |
| 3091 } // namespace internal | 3110 } // namespace internal |
| 3092 } // namespace v8 | 3111 } // namespace v8 |
| OLD | NEW |