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 2838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2849 buffer.Dispose(); | 2849 buffer.Dispose(); |
2850 } | 2850 } |
2851 | 2851 |
2852 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0, | 2852 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "wasm-to-js", 0, |
2853 module_name); | 2853 module_name); |
2854 } | 2854 } |
2855 return code; | 2855 return code; |
2856 } | 2856 } |
2857 | 2857 |
2858 std::pair<JSGraph*, SourcePositionTable*> BuildGraphForWasmFunction( | 2858 std::pair<JSGraph*, SourcePositionTable*> BuildGraphForWasmFunction( |
2859 Zone* zone, wasm::ErrorThrower& thrower, Isolate* isolate, | 2859 Zone* zone, wasm::ErrorThrower* thrower, Isolate* isolate, |
2860 wasm::ModuleEnv*& module_env, const wasm::WasmFunction& function, | 2860 wasm::ModuleEnv*& module_env, const wasm::WasmFunction* function, |
2861 double* decode_ms) { | 2861 double* decode_ms) { |
2862 base::ElapsedTimer decode_timer; | 2862 base::ElapsedTimer decode_timer; |
2863 if (FLAG_trace_wasm_decode_time) { | 2863 if (FLAG_trace_wasm_decode_time) { |
2864 decode_timer.Start(); | 2864 decode_timer.Start(); |
2865 } | 2865 } |
2866 // Create a TF graph during decoding. | 2866 // Create a TF graph during decoding. |
2867 Graph* graph = new (zone) Graph(zone); | 2867 Graph* graph = new (zone) Graph(zone); |
2868 CommonOperatorBuilder* common = new (zone) CommonOperatorBuilder(zone); | 2868 CommonOperatorBuilder* common = new (zone) CommonOperatorBuilder(zone); |
2869 MachineOperatorBuilder* machine = new (zone) MachineOperatorBuilder( | 2869 MachineOperatorBuilder* machine = new (zone) MachineOperatorBuilder( |
2870 zone, MachineType::PointerRepresentation(), | 2870 zone, MachineType::PointerRepresentation(), |
2871 InstructionSelector::SupportedMachineOperatorFlags()); | 2871 InstructionSelector::SupportedMachineOperatorFlags()); |
2872 JSGraph* jsgraph = | 2872 JSGraph* jsgraph = |
2873 new (zone) JSGraph(isolate, graph, common, nullptr, nullptr, machine); | 2873 new (zone) JSGraph(isolate, graph, common, nullptr, nullptr, machine); |
2874 SourcePositionTable* source_position_table = | 2874 SourcePositionTable* source_position_table = |
2875 new (zone) SourcePositionTable(graph); | 2875 new (zone) SourcePositionTable(graph); |
2876 WasmGraphBuilder builder(zone, jsgraph, function.sig, source_position_table); | 2876 WasmGraphBuilder builder(zone, jsgraph, function->sig, source_position_table); |
2877 wasm::FunctionBody body = { | 2877 wasm::FunctionBody body = { |
2878 module_env, function.sig, module_env->module->module_start, | 2878 module_env, function->sig, module_env->module->module_start, |
2879 module_env->module->module_start + function.code_start_offset, | 2879 module_env->module->module_start + function->code_start_offset, |
2880 module_env->module->module_start + function.code_end_offset}; | 2880 module_env->module->module_start + function->code_end_offset}; |
2881 wasm::TreeResult result = | 2881 wasm::TreeResult result = |
2882 wasm::BuildTFGraph(isolate->allocator(), &builder, body); | 2882 wasm::BuildTFGraph(isolate->allocator(), &builder, body); |
2883 | 2883 |
2884 if (machine->Is32()) { | 2884 if (machine->Is32()) { |
2885 Int64Lowering r(graph, machine, common, zone, function.sig); | 2885 Int64Lowering r(graph, machine, common, zone, function->sig); |
2886 r.LowerGraph(); | 2886 r.LowerGraph(); |
2887 } | 2887 } |
2888 | 2888 |
2889 if (result.failed()) { | 2889 if (result.failed()) { |
2890 if (FLAG_trace_wasm_compiler) { | 2890 if (FLAG_trace_wasm_compiler) { |
2891 OFStream os(stdout); | 2891 OFStream os(stdout); |
2892 os << "Compilation failed: " << result << std::endl; | 2892 os << "Compilation failed: " << result << std::endl; |
2893 } | 2893 } |
2894 // Add the function as another context for the exception | 2894 // Add the function as another context for the exception |
2895 ScopedVector<char> buffer(128); | 2895 ScopedVector<char> buffer(128); |
2896 wasm::WasmName name = | 2896 wasm::WasmName name = module_env->module->GetName(function->name_offset, |
2897 module_env->module->GetName(function.name_offset, function.name_length); | 2897 function->name_length); |
2898 SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:", | 2898 SNPrintF(buffer, "Compiling WASM function #%d:%.*s failed:", |
2899 function.func_index, name.length(), name.start()); | 2899 function->func_index, name.length(), name.start()); |
2900 thrower.Failed(buffer.start(), result); | 2900 thrower->Failed(buffer.start(), result); |
2901 return std::make_pair(nullptr, nullptr); | 2901 return std::make_pair(nullptr, nullptr); |
2902 } | 2902 } |
2903 int index = static_cast<int>(function.func_index); | 2903 int index = static_cast<int>(function->func_index); |
2904 if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) { | 2904 if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) { |
2905 PrintAst(isolate->allocator(), body); | 2905 PrintAst(isolate->allocator(), body); |
2906 } | 2906 } |
2907 if (FLAG_trace_wasm_decode_time) { | 2907 if (FLAG_trace_wasm_decode_time) { |
2908 *decode_ms = decode_timer.Elapsed().InMillisecondsF(); | 2908 *decode_ms = decode_timer.Elapsed().InMillisecondsF(); |
2909 } | 2909 } |
2910 return std::make_pair(jsgraph, source_position_table); | 2910 return std::make_pair(jsgraph, source_position_table); |
2911 } | 2911 } |
2912 | 2912 |
2913 // Helper function to compile a single function. | 2913 // Helper function to compile a single function. |
2914 Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate, | 2914 Handle<Code> CompileWasmFunction(wasm::ErrorThrower* thrower, Isolate* isolate, |
2915 wasm::ModuleEnv* module_env, | 2915 wasm::ModuleEnv* module_env, |
2916 const wasm::WasmFunction& function) { | 2916 const wasm::WasmFunction* function) { |
2917 HistogramTimerScope wasm_compile_function_time_scope( | 2917 HistogramTimerScope wasm_compile_function_time_scope( |
2918 isolate->counters()->wasm_compile_function_time()); | 2918 isolate->counters()->wasm_compile_function_time()); |
2919 if (FLAG_trace_wasm_compiler) { | 2919 if (FLAG_trace_wasm_compiler) { |
2920 OFStream os(stdout); | 2920 OFStream os(stdout); |
2921 os << "Compiling WASM function " | 2921 os << "Compiling WASM function " |
2922 << wasm::WasmFunctionName(&function, module_env) << std::endl; | 2922 << wasm::WasmFunctionName(function, module_env) << std::endl; |
2923 os << std::endl; | 2923 os << std::endl; |
2924 } | 2924 } |
2925 | 2925 |
2926 compiler::ZonePool zone_pool(isolate->allocator()); | 2926 compiler::ZonePool zone_pool(isolate->allocator()); |
2927 compiler::ZonePool::Scope graph_zone_scope(&zone_pool); | 2927 compiler::ZonePool::Scope graph_zone_scope(&zone_pool); |
2928 double decode_ms = 0; | 2928 double decode_ms = 0; |
2929 std::pair<JSGraph*, SourcePositionTable*> graph_result = | 2929 std::pair<JSGraph*, SourcePositionTable*> graph_result = |
2930 BuildGraphForWasmFunction(graph_zone_scope.zone(), thrower, isolate, | 2930 BuildGraphForWasmFunction(graph_zone_scope.zone(), thrower, isolate, |
2931 module_env, function, &decode_ms); | 2931 module_env, function, &decode_ms); |
2932 JSGraph* jsgraph = graph_result.first; | 2932 JSGraph* jsgraph = graph_result.first; |
2933 SourcePositionTable* source_positions = graph_result.second; | 2933 SourcePositionTable* source_positions = graph_result.second; |
2934 | 2934 |
2935 if (jsgraph == nullptr) { | 2935 if (jsgraph == nullptr) { |
2936 return Handle<Code>::null(); | 2936 return Handle<Code>::null(); |
2937 } | 2937 } |
2938 | 2938 |
2939 base::ElapsedTimer compile_timer; | 2939 base::ElapsedTimer compile_timer; |
2940 if (FLAG_trace_wasm_decode_time) { | 2940 if (FLAG_trace_wasm_decode_time) { |
2941 compile_timer.Start(); | 2941 compile_timer.Start(); |
2942 } | 2942 } |
2943 // Run the compiler pipeline to generate machine code. | 2943 // Run the compiler pipeline to generate machine code. |
2944 CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor( | 2944 CallDescriptor* descriptor = wasm::ModuleEnv::GetWasmCallDescriptor( |
2945 jsgraph->graph()->zone(), function.sig); | 2945 jsgraph->graph()->zone(), function->sig); |
2946 if (jsgraph->machine()->Is32()) { | 2946 if (jsgraph->machine()->Is32()) { |
2947 descriptor = module_env->GetI32WasmCallDescriptor(jsgraph->graph()->zone(), | 2947 descriptor = module_env->GetI32WasmCallDescriptor(jsgraph->graph()->zone(), |
2948 descriptor); | 2948 descriptor); |
2949 } | 2949 } |
2950 Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION); | 2950 Code::Flags flags = Code::ComputeFlags(Code::WASM_FUNCTION); |
2951 // add flags here if a meaningful name is helpful for debugging. | 2951 // add flags here if a meaningful name is helpful for debugging. |
2952 bool debugging = | 2952 bool debugging = |
2953 #if DEBUG | 2953 #if DEBUG |
2954 true; | 2954 true; |
2955 #else | 2955 #else |
2956 FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph; | 2956 FLAG_print_opt_code || FLAG_trace_turbo || FLAG_trace_turbo_graph; |
2957 #endif | 2957 #endif |
2958 Vector<const char> func_name = module_env->module->GetNameOrNull( | 2958 Vector<const char> func_name = module_env->module->GetNameOrNull( |
2959 function.name_offset, function.name_length); | 2959 function->name_offset, function->name_length); |
2960 Vector<char> buffer; | 2960 Vector<char> buffer; |
2961 if (func_name.is_empty()) { | 2961 if (func_name.is_empty()) { |
2962 if (debugging) { | 2962 if (debugging) { |
2963 buffer = Vector<char>::New(128); | 2963 buffer = Vector<char>::New(128); |
2964 int chars = SNPrintF(buffer, "WASM_function_#%d", function.func_index); | 2964 int chars = SNPrintF(buffer, "WASM_function_#%d", function->func_index); |
2965 func_name = Vector<const char>::cast(buffer.SubVector(0, chars)); | 2965 func_name = Vector<const char>::cast(buffer.SubVector(0, chars)); |
2966 } else { | 2966 } else { |
2967 func_name = ArrayVector("wasm"); | 2967 func_name = ArrayVector("wasm"); |
2968 } | 2968 } |
2969 } | 2969 } |
2970 CompilationInfo info(func_name, isolate, jsgraph->graph()->zone(), flags); | 2970 CompilationInfo info(func_name, isolate, jsgraph->graph()->zone(), flags); |
2971 base::SmartPointer<CompilationJob> job(Pipeline::NewWasmCompilationJob( | 2971 base::SmartPointer<CompilationJob> job(Pipeline::NewWasmCompilationJob( |
2972 &info, jsgraph->graph(), descriptor, source_positions)); | 2972 &info, jsgraph->graph(), descriptor, source_positions)); |
2973 Handle<Code> code = Handle<Code>::null(); | 2973 Handle<Code> code = Handle<Code>::null(); |
2974 if (job->OptimizeGraph() == CompilationJob::SUCCEEDED && | 2974 if (job->OptimizeGraph() == CompilationJob::SUCCEEDED && |
2975 job->GenerateCode() == CompilationJob::SUCCEEDED) { | 2975 job->GenerateCode() == CompilationJob::SUCCEEDED) { |
2976 code = info.code(); | 2976 code = info.code(); |
2977 } | 2977 } |
2978 | 2978 |
2979 buffer.Dispose(); | 2979 buffer.Dispose(); |
2980 if (!code.is_null()) { | 2980 if (!code.is_null()) { |
2981 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, "WASM_function", | 2981 RecordFunctionCompilation( |
2982 function.func_index, | 2982 Logger::FUNCTION_TAG, &info, "WASM_function", function->func_index, |
2983 module_env->module->GetName( | 2983 module_env->module->GetName(function->name_offset, |
2984 function.name_offset, function.name_length)); | 2984 function->name_length)); |
2985 } | 2985 } |
2986 | 2986 |
2987 if (FLAG_trace_wasm_decode_time) { | 2987 if (FLAG_trace_wasm_decode_time) { |
2988 double compile_ms = compile_timer.Elapsed().InMillisecondsF(); | 2988 double compile_ms = compile_timer.Elapsed().InMillisecondsF(); |
2989 PrintF( | 2989 PrintF( |
2990 "wasm-compile ok: %d bytes, %0.3f ms decode, %d nodes, %0.3f ms " | 2990 "wasm-compile ok: %d bytes, %0.3f ms decode, %d nodes, %0.3f ms " |
2991 "compile\n", | 2991 "compile\n", |
2992 static_cast<int>(function.code_end_offset - function.code_start_offset), | 2992 static_cast<int>(function->code_end_offset - |
| 2993 function->code_start_offset), |
2993 decode_ms, static_cast<int>(jsgraph->graph()->NodeCount()), compile_ms); | 2994 decode_ms, static_cast<int>(jsgraph->graph()->NodeCount()), compile_ms); |
2994 } | 2995 } |
2995 // TODO(bradnelson): Improve histogram handling of size_t. | 2996 // TODO(bradnelson): Improve histogram handling of size_t. |
2996 isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample( | 2997 isolate->counters()->wasm_compile_function_peak_memory_bytes()->AddSample( |
2997 static_cast<int>(jsgraph->graph()->zone()->allocation_size())); | 2998 static_cast<int>(jsgraph->graph()->zone()->allocation_size())); |
2998 graph_zone_scope.Destroy(); | 2999 graph_zone_scope.Destroy(); |
2999 return code; | 3000 return code; |
3000 } | 3001 } |
3001 | 3002 |
| 3003 class WasmCompilationUnit { |
| 3004 public: |
| 3005 WasmCompilationUnit(wasm::ErrorThrower* thrower, Isolate* isolate, |
| 3006 wasm::ModuleEnv* module_env, |
| 3007 const wasm::WasmFunction* function) |
| 3008 : thrower_(thrower), |
| 3009 isolate_(isolate), |
| 3010 module_env_(module_env), |
| 3011 function_(function) {} |
| 3012 |
| 3013 void ExecuteCompilation() { |
| 3014 if (function_->external) { |
| 3015 return; |
| 3016 } |
| 3017 // TODO(ahaas): The parallelizable parts of the compilation should move from |
| 3018 // FinishCompilation to here. |
| 3019 } |
| 3020 |
| 3021 Handle<Code> FinishCompilation() { |
| 3022 return CompileWasmFunction(thrower_, isolate_, module_env_, function_); |
| 3023 } |
| 3024 |
| 3025 wasm::ErrorThrower* thrower_; |
| 3026 Isolate* isolate_; |
| 3027 wasm::ModuleEnv* module_env_; |
| 3028 const wasm::WasmFunction* function_; |
| 3029 }; |
| 3030 |
| 3031 WasmCompilationUnit* CreateWasmCompilationUnit( |
| 3032 wasm::ErrorThrower* thrower, Isolate* isolate, wasm::ModuleEnv* module_env, |
| 3033 const wasm::WasmFunction* function) { |
| 3034 return new WasmCompilationUnit(thrower, isolate, module_env, function); |
| 3035 } |
| 3036 |
| 3037 void ExecuteCompilation(WasmCompilationUnit* unit) { |
| 3038 unit->ExecuteCompilation(); |
| 3039 } |
| 3040 |
| 3041 Handle<Code> FinishCompilation(WasmCompilationUnit* unit) { |
| 3042 Handle<Code> result = unit->FinishCompilation(); |
| 3043 delete unit; |
| 3044 return result; |
| 3045 } |
3002 | 3046 |
3003 } // namespace compiler | 3047 } // namespace compiler |
3004 } // namespace internal | 3048 } // namespace internal |
3005 } // namespace v8 | 3049 } // namespace v8 |
OLD | NEW |