Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: src/wasm/wasm-module.cc

Issue 2629853004: [wasm] Skip serialization of breakpoints and certion stubs (Closed)
Patch Set: Move implementation to .cc file Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/snapshot/code-serializer.cc ('k') | src/wasm/wasm-objects.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <memory> 5 #include <memory>
6 6
7 #include "src/assembler-inl.h" 7 #include "src/assembler-inl.h"
8 #include "src/base/adapters.h" 8 #include "src/base/adapters.h"
9 #include "src/base/atomic-utils.h" 9 #include "src/base/atomic-utils.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
153 DCHECK(code_table->get(i)->IsCode()); 153 DCHECK(code_table->get(i)->IsCode());
154 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i))); 154 Handle<Code> code = Handle<Code>(Code::cast(code_table->get(i)));
155 AllowDeferredHandleDereference embedding_raw_address; 155 AllowDeferredHandleDereference embedding_raw_address;
156 int mask = 1 << RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE; 156 int mask = 1 << RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE;
157 for (RelocIterator it(*code, mask); !it.done(); it.next()) { 157 for (RelocIterator it(*code, mask); !it.done(); it.next()) {
158 it.rinfo()->update_wasm_function_table_size_reference(old_size, new_size); 158 it.rinfo()->update_wasm_function_table_size_reference(old_size, new_size);
159 } 159 }
160 } 160 }
161 } 161 }
162 162
163 Handle<Code> CreatePlaceholder(Factory* factory, Code::Kind kind) {
164 byte buffer[] = {0, 0, 0, 0}; // fake instructions.
165 CodeDesc desc = {
166 buffer, arraysize(buffer), arraysize(buffer), 0, 0, nullptr, 0, nullptr};
167 return factory->NewCode(desc, Code::KindField::encode(kind),
168 Handle<Object>::null());
169 }
170
171 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) { 163 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) {
172 for (int i = 0; i < code_table->length(); ++i) { 164 for (int i = 0; i < code_table->length(); ++i) {
173 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i); 165 Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
174 Assembler::FlushICache(isolate, code->instruction_start(), 166 Assembler::FlushICache(isolate, code->instruction_start(),
175 code->instruction_size()); 167 code->instruction_size());
176 } 168 }
177 } 169 }
178 170
179 // Fetches the compilation unit of a wasm function and executes its parallel 171 // Fetches the compilation unit of a wasm function and executes its parallel
180 // phase. 172 // phase.
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 Handle<Code> code = Handle<Code>::null(); 397 Handle<Code> code = Handle<Code>::null();
406 // Compile the function. 398 // Compile the function.
407 code = compiler::WasmCompilationUnit::CompileWasmFunction( 399 code = compiler::WasmCompilationUnit::CompileWasmFunction(
408 thrower, isolate, module_env, &func); 400 thrower, isolate, module_env, &func);
409 if (code.is_null()) { 401 if (code.is_null()) {
410 WasmName str = module_env->GetName(&func); 402 WasmName str = module_env->GetName(&func);
411 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(), 403 thrower->CompileError("Compilation of #%d:%.*s failed.", i, str.length(),
412 str.start()); 404 str.start());
413 break; 405 break;
414 } 406 }
415 // Install the code into the linker table. 407 // Install the code into the linker table.
416 functions[i] = code; 408 functions[i] = code;
417 } 409 }
418 } 410 }
419 411
420 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) { 412 int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) {
421 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc)); 413 DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc));
422 decoder.Reset(pc + 1, pc + 6); 414 decoder.Reset(pc + 1, pc + 6);
423 uint32_t call_idx = decoder.consume_u32v("call index"); 415 uint32_t call_idx = decoder.consume_u32v("call index");
424 DCHECK(decoder.ok()); 416 DCHECK(decoder.ok());
425 DCHECK_GE(kMaxInt, call_idx); 417 DCHECK_GE(kMaxInt, call_idx);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 DCHECK_EQ(start, compiled_module->module()->num_imported_functions); 454 DCHECK_EQ(start, compiled_module->module()->num_imported_functions);
463 Context* context = compiled_module->ptr_to_native_context(); 455 Context* context = compiled_module->ptr_to_native_context();
464 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | 456 int mode_mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
465 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); 457 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
466 458
467 // Allocate decoder outside of the loop and reuse it to decode all function 459 // Allocate decoder outside of the loop and reuse it to decode all function
468 // indexes. 460 // indexes.
469 wasm::Decoder decoder(nullptr, nullptr); 461 wasm::Decoder decoder(nullptr, nullptr);
470 int num_wasm_functions = static_cast<int>(wasm_functions->size()); 462 int num_wasm_functions = static_cast<int>(wasm_functions->size());
471 int func_index = start; 463 int func_index = start;
464 // We patch WASM_FUNCTION and WASM_TO_JS_FUNCTION during re-instantiation,
465 // and illegal builtins initially and after deserialization.
466 auto is_at_wasm_call = [](RelocIterator& it) {
467 Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
468 return code->kind() == Code::WASM_FUNCTION ||
469 code->kind() == Code::WASM_TO_JS_FUNCTION ||
470 code->builtin_index() == Builtins::kIllegal;
471 };
472
472 // Patch all wasm functions. 473 // Patch all wasm functions.
473 for (; func_index < num_wasm_functions; ++func_index) { 474 for (; func_index < num_wasm_functions; ++func_index) {
474 Code* wasm_function = Code::cast(new_functions->get(func_index)); 475 Code* wasm_function = Code::cast(new_functions->get(func_index));
475 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION); 476 DCHECK(wasm_function->kind() == Code::WASM_FUNCTION);
476 // Iterate simultaneously over the relocation information and the source 477 // Iterate simultaneously over the relocation information and the source
477 // position table. For each call in the reloc info, move the source position 478 // position table. For each call in the reloc info, move the source position
478 // iterator forward to that position to find the byte offset of the 479 // iterator forward to that position to find the byte offset of the
479 // respective call. Then extract the call index from the module wire bytes 480 // respective call. Then extract the call index from the module wire bytes
480 // to find the new compiled function. 481 // to find the new compiled function.
481 SourcePositionTableIterator source_pos_iterator( 482 SourcePositionTableIterator source_pos_iterator(
482 wasm_function->source_position_table()); 483 wasm_function->source_position_table());
483 const byte* func_bytes = 484 const byte* func_bytes =
484 module_bytes->GetChars() + 485 module_bytes->GetChars() +
485 compiled_module->module()->functions[func_index].code_start_offset; 486 compiled_module->module()->functions[func_index].code_start_offset;
486 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) { 487 for (RelocIterator it(wasm_function, mode_mask); !it.done(); it.next()) {
487 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) { 488 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) {
488 PatchContext(it, context); 489 PatchContext(it, context);
489 continue; 490 continue;
490 } 491 }
491 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); 492 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode()));
492 Code::Kind kind = 493 if (!is_at_wasm_call(it)) continue;
493 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind();
494 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION)
495 continue;
496 size_t offset = it.rinfo()->pc() - wasm_function->instruction_start(); 494 size_t offset = it.rinfo()->pc() - wasm_function->instruction_start();
497 int byte_pos = 495 int byte_pos =
498 AdvanceSourcePositionTableIterator(source_pos_iterator, offset); 496 AdvanceSourcePositionTableIterator(source_pos_iterator, offset);
499 int called_func_index = 497 int called_func_index =
500 ExtractDirectCallIndex(decoder, func_bytes + byte_pos); 498 ExtractDirectCallIndex(decoder, func_bytes + byte_pos);
501 Code* new_code = Code::cast(new_functions->get(called_func_index)); 499 Code* new_code = Code::cast(new_functions->get(called_func_index));
502 it.rinfo()->set_target_address(new_code->instruction_start(), 500 it.rinfo()->set_target_address(new_code->instruction_start(),
503 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); 501 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
504 } 502 }
505 } 503 }
506 // Patch all exported functions. 504 // Patch all exported functions.
507 for (auto exp : module->export_table) { 505 for (auto exp : module->export_table) {
508 if (exp.kind != kExternalFunction) continue; 506 if (exp.kind != kExternalFunction) continue;
509 Code* export_wrapper = Code::cast(new_functions->get(func_index)); 507 Code* export_wrapper = Code::cast(new_functions->get(func_index));
510 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind()); 508 DCHECK_EQ(Code::JS_TO_WASM_FUNCTION, export_wrapper->kind());
511 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION. 509 // There must be exactly one call to WASM_FUNCTION or WASM_TO_JS_FUNCTION.
512 int num_wasm_calls = 0; 510 int num_wasm_calls = 0;
513 for (RelocIterator it(export_wrapper, mode_mask); !it.done(); it.next()) { 511 for (RelocIterator it(export_wrapper, mode_mask); !it.done(); it.next()) {
514 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) { 512 if (RelocInfo::IsEmbeddedObject(it.rinfo()->rmode())) {
515 PatchContext(it, context); 513 PatchContext(it, context);
516 continue; 514 continue;
517 } 515 }
518 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode())); 516 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode()));
519 Code::Kind kind = 517 if (!is_at_wasm_call(it)) continue;
520 Code::GetCodeFromTargetAddress(it.rinfo()->target_address())->kind();
521 if (kind != Code::WASM_FUNCTION && kind != Code::WASM_TO_JS_FUNCTION)
522 continue;
523 ++num_wasm_calls; 518 ++num_wasm_calls;
524 Code* new_code = Code::cast(new_functions->get(exp.index)); 519 Code* new_code = Code::cast(new_functions->get(exp.index));
525 DCHECK(new_code->kind() == Code::WASM_FUNCTION || 520 DCHECK(new_code->kind() == Code::WASM_FUNCTION ||
526 new_code->kind() == Code::WASM_TO_JS_FUNCTION); 521 new_code->kind() == Code::WASM_TO_JS_FUNCTION);
527 it.rinfo()->set_target_address(new_code->instruction_start(), 522 it.rinfo()->set_target_address(new_code->instruction_start(),
528 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH); 523 UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
529 } 524 }
530 DCHECK_EQ(1, num_wasm_calls); 525 DCHECK_EQ(1, num_wasm_calls);
531 func_index++; 526 func_index++;
532 } 527 }
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 914
920 ModuleBytesEnv module_env(this, &temp_instance, wire_bytes); 915 ModuleBytesEnv module_env(this, &temp_instance, wire_bytes);
921 916
922 // The {code_table} array contains import wrappers and functions (which 917 // The {code_table} array contains import wrappers and functions (which
923 // are both included in {functions.size()}, and export wrappers. 918 // are both included in {functions.size()}, and export wrappers.
924 int code_table_size = 919 int code_table_size =
925 static_cast<int>(functions.size() + num_exported_functions); 920 static_cast<int>(functions.size() + num_exported_functions);
926 Handle<FixedArray> code_table = 921 Handle<FixedArray> code_table =
927 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED); 922 factory->NewFixedArray(static_cast<int>(code_table_size), TENURED);
928 923
929 // Initialize the code table with placeholders. 924 // Initialize the code table with the illegal builtin. All call sites will be
930 Handle<Code> code_placeholder = 925 // patched at instantiation.
931 CreatePlaceholder(factory, Code::WASM_FUNCTION); 926 Handle<Code> illegal_builtin = isolate->builtins()->Illegal();
932 for (uint32_t i = 0; i < functions.size(); ++i) { 927 for (uint32_t i = 0; i < functions.size(); ++i) {
933 code_table->set(static_cast<int>(i), *code_placeholder); 928 code_table->set(static_cast<int>(i), *illegal_builtin);
934 temp_instance.function_code[i] = code_placeholder; 929 temp_instance.function_code[i] = illegal_builtin;
935 } 930 }
936 931
937 isolate->counters()->wasm_functions_per_module()->AddSample( 932 isolate->counters()->wasm_functions_per_module()->AddSample(
938 static_cast<int>(functions.size())); 933 static_cast<int>(functions.size()));
939 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) { 934 if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) {
940 // Avoid a race condition by collecting results into a second vector. 935 // Avoid a race condition by collecting results into a second vector.
941 std::vector<Handle<Code>> results; 936 std::vector<Handle<Code>> results(temp_instance.function_code);
942 results.reserve(temp_instance.function_code.size());
943 for (size_t i = 0; i < temp_instance.function_code.size(); ++i) {
944 results.push_back(temp_instance.function_code[i]);
945 }
946 CompileInParallel(isolate, &module_env, results, thrower); 937 CompileInParallel(isolate, &module_env, results, thrower);
947 938 temp_instance.function_code.swap(results);
948 for (size_t i = 0; i < results.size(); ++i) {
949 temp_instance.function_code[i] = results[i];
950 }
951 } else { 939 } else {
952 CompileSequentially(isolate, &module_env, temp_instance.function_code, 940 CompileSequentially(isolate, &module_env, temp_instance.function_code,
953 thrower); 941 thrower);
954 } 942 }
955 if (thrower->error()) return nothing; 943 if (thrower->error()) return nothing;
956 944
957 // At this point, compilation has completed. Update the code table. 945 // At this point, compilation has completed. Update the code table.
958 for (size_t i = FLAG_skip_compiling_wasm_funcs; 946 for (size_t i = FLAG_skip_compiling_wasm_funcs;
959 i < temp_instance.function_code.size(); ++i) { 947 i < temp_instance.function_code.size(); ++i) {
960 Code* code = *temp_instance.function_code[i]; 948 Code* code = *temp_instance.function_code[i];
(...skipping 1610 matching lines...) Expand 10 before | Expand all | Expand 10 after
2571 2559
2572 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(), 2560 JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(),
2573 NONE); 2561 NONE);
2574 JSObject::AddProperty(entry, kind_string, export_kind, NONE); 2562 JSObject::AddProperty(entry, kind_string, export_kind, NONE);
2575 2563
2576 storage->set(index, *entry); 2564 storage->set(index, *entry);
2577 } 2565 }
2578 2566
2579 return array_object; 2567 return array_object;
2580 } 2568 }
OLDNEW
« no previous file with comments | « src/snapshot/code-serializer.cc ('k') | src/wasm/wasm-objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698