Index: src/wasm/wasm-objects.cc |
diff --git a/src/wasm/wasm-objects.cc b/src/wasm/wasm-objects.cc |
index fbe64eb6159c89054b3066e26919d7e793418e02..7f68c020c759537ad68cbdd02a28721fdc1b32df 100644 |
--- a/src/wasm/wasm-objects.cc |
+++ b/src/wasm/wasm-objects.cc |
@@ -3,6 +3,8 @@ |
// found in the LICENSE file. |
#include "src/wasm/wasm-objects.h" |
+ |
+#include "src/wasm/module-decoder.h" |
#include "src/wasm/wasm-module.h" |
#define TRACE(...) \ |
@@ -446,6 +448,99 @@ bool WasmCompiledModule::GetPositionInfo(uint32_t position, |
return true; |
} |
+namespace { |
+Handle<ByteArray> GetDecodedAsmJsOffsetTable( |
+ Handle<WasmCompiledModule> compiled_module, Isolate* isolate) { |
+ DCHECK(compiled_module->has_asm_js_offset_table()); |
+ Handle<ByteArray> offset_table = compiled_module->asm_js_offset_table(); |
+ |
+ // The last byte in the asm_js_offset_tables ByteArray tells whether it is |
+ // still encoded (0) or decoded (1). |
+ enum AsmJsTableType : int { Encoded = 0, Decoded = 1 }; |
+ int table_type = offset_table->get(offset_table->length() - 1); |
+ DCHECK(table_type == Encoded || table_type == Decoded); |
+ if (table_type == Decoded) return offset_table; |
+ |
+ AsmJsOffsetsResult asm_offsets; |
+ { |
+ DisallowHeapAllocation no_gc; |
+ const byte* bytes_start = offset_table->GetDataStartAddress(); |
+ const byte* bytes_end = bytes_start + offset_table->length() - 1; |
+ asm_offsets = wasm::DecodeAsmJsOffsets(bytes_start, bytes_end); |
+ } |
+ // Wasm bytes must be valid and must contain asm.js offset table. |
+ DCHECK(asm_offsets.ok()); |
+ DCHECK_GE(static_cast<size_t>(kMaxInt), asm_offsets.val.size()); |
+ int num_functions = static_cast<int>(asm_offsets.val.size()); |
+ int num_imported_functions = |
+ static_cast<int>(compiled_module->module()->num_imported_functions); |
+ DCHECK_EQ(compiled_module->module()->functions.size(), |
+ static_cast<size_t>(num_functions) + num_imported_functions); |
+ // One byte to encode that this is a decoded table. |
+ int total_size = 1; |
+ for (int func = 0; func < num_functions; ++func) { |
+ size_t new_size = asm_offsets.val[func].size() * 2 * kIntSize; |
+ DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - total_size); |
+ total_size += static_cast<int>(new_size); |
+ } |
+ Handle<ByteArray> decoded_table = |
+ isolate->factory()->NewByteArray(total_size, TENURED); |
+ decoded_table->set(total_size - 1, AsmJsTableType::Decoded); |
+ compiled_module->set_asm_js_offset_table(decoded_table); |
+ |
+ int idx = 0; |
+ std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions; |
+ for (int func = 0; func < num_functions; ++func) { |
+ std::vector<std::pair<int, int>>& func_asm_offsets = asm_offsets.val[func]; |
+ if (func_asm_offsets.empty()) continue; |
+ int func_offset = |
+ wasm_funs[num_imported_functions + func].code_start_offset; |
+ for (std::pair<int, int> p : func_asm_offsets) { |
+ // Byte offsets must be strictly monotonously increasing: |
+ DCHECK(idx == 0 || |
+ func_offset + p.first > decoded_table->get_int(idx - 2)); |
+ decoded_table->set_int(idx++, func_offset + p.first); |
+ decoded_table->set_int(idx++, p.second); |
+ } |
+ } |
+ DCHECK_EQ(total_size, idx * kIntSize + 1); |
+ return decoded_table; |
+} |
+} // namespace |
+ |
+int WasmCompiledModule::GetAsmJsSourcePosition( |
+ Handle<WasmCompiledModule> compiled_module, uint32_t func_index, |
+ uint32_t byte_offset) { |
+ Isolate* isolate = compiled_module->GetIsolate(); |
+ Handle<ByteArray> offset_table = |
+ GetDecodedAsmJsOffsetTable(compiled_module, isolate); |
+ |
+ DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
+ uint32_t func_code_offset = |
+ compiled_module->module()->functions[func_index].code_start_offset; |
+ uint32_t total_offset = func_code_offset + byte_offset; |
+ |
+ // Binary search for the total byte offset. |
+ int left = 0; // inclusive |
+ int right = offset_table->length() / kIntSize / 2; // exclusive |
+ DCHECK_LT(left, right); |
+ while (right - left > 1) { |
+ int mid = left + (right - left) / 2; |
+ int mid_entry = offset_table->get_int(2 * mid); |
+ DCHECK_GE(kMaxInt, mid_entry); |
+ if (static_cast<uint32_t>(mid_entry) <= total_offset) { |
+ left = mid; |
+ } else { |
+ right = mid; |
+ } |
+ } |
+ // There should be an entry for each position that could show up on the stack |
+ // trace: |
+ DCHECK_EQ(total_offset, |
+ static_cast<uint32_t>(offset_table->get_int(2 * left))); |
+ return offset_table->get_int(2 * left + 1); |
+} |
+ |
Handle<WasmInstanceWrapper> WasmInstanceWrapper::New( |
Isolate* isolate, Handle<WasmInstanceObject> instance) { |
Handle<FixedArray> array = |