| 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/wasm/wasm-objects.h" | 5 #include "src/wasm/wasm-objects.h" |
| 6 #include "src/utils.h" | 6 #include "src/utils.h" |
| 7 | 7 |
| 8 #include "src/debug/debug-interface.h" | 8 #include "src/debug/debug-interface.h" |
| 9 #include "src/wasm/module-decoder.h" | 9 #include "src/wasm/module-decoder.h" |
| 10 #include "src/wasm/wasm-module.h" | 10 #include "src/wasm/wasm-module.h" |
| 11 #include "src/wasm/wasm-text.h" | 11 #include "src/wasm/wasm-text.h" |
| 12 | 12 |
| 13 #define TRACE(...) \ | 13 #define TRACE(...) \ |
| 14 do { \ | 14 do { \ |
| 15 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ | 15 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ |
| 16 } while (false) | 16 } while (false) |
| 17 | 17 |
| 18 #define TRACE_CHAIN(instance) \ | 18 #define TRACE_CHAIN(instance) \ |
| 19 do { \ | 19 do { \ |
| 20 instance->PrintInstancesChain(); \ | 20 instance->PrintInstancesChain(); \ |
| 21 } while (false) | 21 } while (false) |
| 22 | 22 |
| 23 using namespace v8::internal; | 23 using namespace v8::internal; |
| 24 using namespace v8::internal::wasm; | 24 using namespace v8::internal::wasm; |
| 25 | 25 |
| 26 #define DEFINE_ACCESSORS(Container, name, field, type) \ | 26 #define DEFINE_GETTER0(getter, Container, name, field, type) \ |
| 27 type* Container::get_##name() { \ | 27 type* Container::name() { return type::cast(getter(field)); } |
| 28 return type::cast(GetInternalField(field)); \ | 28 |
| 29 } \ | 29 #define DEFINE_ACCESSORS0(getter, setter, Container, name, field, type) \ |
| 30 void Container::set_##name(type* value) { \ | 30 DEFINE_GETTER0(getter, Container, name, field, type) \ |
| 31 return SetInternalField(field, value); \ | 31 void Container::set_##name(type* value) { return setter(field, value); } |
| 32 |
| 33 #define DEFINE_OPTIONAL_ACCESSORS0(getter, setter, Container, name, field, \ |
| 34 type) \ |
| 35 DEFINE_ACCESSORS0(getter, setter, Container, name, field, type) \ |
| 36 bool Container::has_##name() { \ |
| 37 return !getter(field)->IsUndefined(GetIsolate()); \ |
| 32 } | 38 } |
| 33 | 39 |
| 34 #define DEFINE_OPTIONAL_ACCESSORS(Container, name, field, type) \ | 40 #define DEFINE_OBJ_GETTER(Container, name, field, type) \ |
| 35 bool Container::has_##name() { \ | 41 DEFINE_GETTER0(GetInternalField, Container, name, field, type) |
| 36 return !GetInternalField(field)->IsUndefined(GetIsolate()); \ | 42 #define DEFINE_OBJ_ACCESSORS(Container, name, field, type) \ |
| 37 } \ | 43 DEFINE_ACCESSORS0(GetInternalField, SetInternalField, Container, name, \ |
| 38 type* Container::get_##name() { \ | 44 field, type) |
| 39 return type::cast(GetInternalField(field)); \ | 45 #define DEFINE_OPTIONAL_OBJ_ACCESSORS(Container, name, field, type) \ |
| 40 } \ | 46 DEFINE_OPTIONAL_ACCESSORS0(GetInternalField, SetInternalField, Container, \ |
| 41 void Container::set_##name(type* value) { \ | 47 name, field, type) |
| 42 return SetInternalField(field, value); \ | 48 #define DEFINE_ARR_GETTER(Container, name, field, type) \ |
| 43 } | 49 DEFINE_GETTER0(get, Container, name, field, type) |
| 50 #define DEFINE_ARR_ACCESSORS(Container, name, field, type) \ |
| 51 DEFINE_ACCESSORS0(get, set, Container, name, field, type) |
| 52 #define DEFINE_OPTIONAL_ARR_ACCESSORS(Container, name, field, type) \ |
| 53 DEFINE_OPTIONAL_ACCESSORS0(get, set, Container, name, field, type) |
| 44 | 54 |
| 45 #define DEFINE_GETTER(Container, name, field, type) \ | 55 namespace { |
| 46 type* Container::get_##name() { return type::cast(GetInternalField(field)); } | |
| 47 | 56 |
| 48 static uint32_t SafeUint32(Object* value) { | 57 uint32_t SafeUint32(Object* value) { |
| 49 if (value->IsSmi()) { | 58 if (value->IsSmi()) { |
| 50 int32_t val = Smi::cast(value)->value(); | 59 int32_t val = Smi::cast(value)->value(); |
| 51 CHECK_GE(val, 0); | 60 CHECK_GE(val, 0); |
| 52 return static_cast<uint32_t>(val); | 61 return static_cast<uint32_t>(val); |
| 53 } | 62 } |
| 54 DCHECK(value->IsHeapNumber()); | 63 DCHECK(value->IsHeapNumber()); |
| 55 HeapNumber* num = HeapNumber::cast(value); | 64 HeapNumber* num = HeapNumber::cast(value); |
| 56 CHECK_GE(num->value(), 0.0); | 65 CHECK_GE(num->value(), 0.0); |
| 57 CHECK_LE(num->value(), kMaxUInt32); | 66 CHECK_LE(num->value(), kMaxUInt32); |
| 58 return static_cast<uint32_t>(num->value()); | 67 return static_cast<uint32_t>(num->value()); |
| 59 } | 68 } |
| 60 | 69 |
| 61 static int32_t SafeInt32(Object* value) { | 70 int32_t SafeInt32(Object* value) { |
| 62 if (value->IsSmi()) { | 71 if (value->IsSmi()) { |
| 63 return Smi::cast(value)->value(); | 72 return Smi::cast(value)->value(); |
| 64 } | 73 } |
| 65 DCHECK(value->IsHeapNumber()); | 74 DCHECK(value->IsHeapNumber()); |
| 66 HeapNumber* num = HeapNumber::cast(value); | 75 HeapNumber* num = HeapNumber::cast(value); |
| 67 CHECK_GE(num->value(), Smi::kMinValue); | 76 CHECK_GE(num->value(), Smi::kMinValue); |
| 68 CHECK_LE(num->value(), Smi::kMaxValue); | 77 CHECK_LE(num->value(), Smi::kMaxValue); |
| 69 return static_cast<int32_t>(num->value()); | 78 return static_cast<int32_t>(num->value()); |
| 70 } | 79 } |
| 71 | 80 |
| 81 } // namespace |
| 82 |
| 72 Handle<WasmModuleObject> WasmModuleObject::New( | 83 Handle<WasmModuleObject> WasmModuleObject::New( |
| 73 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { | 84 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { |
| 74 ModuleOrigin origin = compiled_module->module()->origin; | 85 ModuleOrigin origin = compiled_module->module()->origin; |
| 75 | 86 |
| 76 Handle<JSObject> module_object; | 87 Handle<JSObject> module_object; |
| 77 if (origin == ModuleOrigin::kWasmOrigin) { | 88 if (origin == ModuleOrigin::kWasmOrigin) { |
| 78 Handle<JSFunction> module_cons( | 89 Handle<JSFunction> module_cons( |
| 79 isolate->native_context()->wasm_module_constructor()); | 90 isolate->native_context()->wasm_module_constructor()); |
| 80 module_object = isolate->factory()->NewJSObject(module_cons); | 91 module_object = isolate->factory()->NewJSObject(module_cons); |
| 81 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | 92 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 100 DCHECK(object->IsJSObject()); | 111 DCHECK(object->IsJSObject()); |
| 101 // TODO(titzer): brand check for WasmModuleObject. | 112 // TODO(titzer): brand check for WasmModuleObject. |
| 102 return reinterpret_cast<WasmModuleObject*>(object); | 113 return reinterpret_cast<WasmModuleObject*>(object); |
| 103 } | 114 } |
| 104 | 115 |
| 105 bool WasmModuleObject::IsWasmModuleObject(Object* object) { | 116 bool WasmModuleObject::IsWasmModuleObject(Object* object) { |
| 106 return object->IsJSObject() && | 117 return object->IsJSObject() && |
| 107 JSObject::cast(object)->GetInternalFieldCount() == kFieldCount; | 118 JSObject::cast(object)->GetInternalFieldCount() == kFieldCount; |
| 108 } | 119 } |
| 109 | 120 |
| 110 DEFINE_GETTER(WasmModuleObject, compiled_module, kCompiledModule, | 121 DEFINE_OBJ_GETTER(WasmModuleObject, compiled_module, kCompiledModule, |
| 111 WasmCompiledModule) | 122 WasmCompiledModule) |
| 112 | 123 |
| 113 Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial, | 124 Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial, |
| 114 uint32_t maximum, | 125 uint32_t maximum, |
| 115 Handle<FixedArray>* js_functions) { | 126 Handle<FixedArray>* js_functions) { |
| 116 Handle<JSFunction> table_ctor( | 127 Handle<JSFunction> table_ctor( |
| 117 isolate->native_context()->wasm_table_constructor()); | 128 isolate->native_context()->wasm_table_constructor()); |
| 118 Handle<JSObject> table_obj = isolate->factory()->NewJSObject(table_ctor); | 129 Handle<JSObject> table_obj = isolate->factory()->NewJSObject(table_ctor); |
| 119 *js_functions = isolate->factory()->NewFixedArray(initial); | 130 *js_functions = isolate->factory()->NewFixedArray(initial); |
| 120 Object* null = isolate->heap()->null_value(); | 131 Object* null = isolate->heap()->null_value(); |
| 121 for (int i = 0; i < static_cast<int>(initial); ++i) { | 132 for (int i = 0; i < static_cast<int>(initial); ++i) { |
| 122 (*js_functions)->set(i, null); | 133 (*js_functions)->set(i, null); |
| 123 } | 134 } |
| 124 table_obj->SetInternalField(kFunctions, *(*js_functions)); | 135 table_obj->SetInternalField(kFunctions, *(*js_functions)); |
| 125 table_obj->SetInternalField(kMaximum, | 136 table_obj->SetInternalField(kMaximum, |
| 126 static_cast<Object*>(Smi::FromInt(maximum))); | 137 static_cast<Object*>(Smi::FromInt(maximum))); |
| 127 | 138 |
| 128 Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0); | 139 Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0); |
| 129 table_obj->SetInternalField(kDispatchTables, *dispatch_tables); | 140 table_obj->SetInternalField(kDispatchTables, *dispatch_tables); |
| 130 Handle<Symbol> table_sym(isolate->native_context()->wasm_table_sym()); | 141 Handle<Symbol> table_sym(isolate->native_context()->wasm_table_sym()); |
| 131 Object::SetProperty(table_obj, table_sym, table_obj, STRICT).Check(); | 142 Object::SetProperty(table_obj, table_sym, table_obj, STRICT).Check(); |
| 132 return Handle<WasmTableObject>::cast(table_obj); | 143 return Handle<WasmTableObject>::cast(table_obj); |
| 133 } | 144 } |
| 134 | 145 |
| 135 DEFINE_GETTER(WasmTableObject, dispatch_tables, kDispatchTables, FixedArray) | 146 DEFINE_OBJ_GETTER(WasmTableObject, dispatch_tables, kDispatchTables, FixedArray) |
| 136 | 147 |
| 137 Handle<FixedArray> WasmTableObject::AddDispatchTable( | 148 Handle<FixedArray> WasmTableObject::AddDispatchTable( |
| 138 Isolate* isolate, Handle<WasmTableObject> table_obj, | 149 Isolate* isolate, Handle<WasmTableObject> table_obj, |
| 139 Handle<WasmInstanceObject> instance, int table_index, | 150 Handle<WasmInstanceObject> instance, int table_index, |
| 140 Handle<FixedArray> dispatch_table) { | 151 Handle<FixedArray> dispatch_table) { |
| 141 Handle<FixedArray> dispatch_tables( | 152 Handle<FixedArray> dispatch_tables( |
| 142 FixedArray::cast(table_obj->GetInternalField(kDispatchTables)), isolate); | 153 FixedArray::cast(table_obj->GetInternalField(kDispatchTables)), isolate); |
| 143 DCHECK_EQ(0, dispatch_tables->length() % 3); | 154 DCHECK_EQ(0, dispatch_tables->length() % 3); |
| 144 | 155 |
| 145 if (instance.is_null()) return dispatch_tables; | 156 if (instance.is_null()) return dispatch_tables; |
| 146 // TODO(titzer): use weak cells here to avoid leaking instances. | 157 // TODO(titzer): use weak cells here to avoid leaking instances. |
| 147 | 158 |
| 148 // Grow the dispatch table and add a new triple at the end. | 159 // Grow the dispatch table and add a new triple at the end. |
| 149 Handle<FixedArray> new_dispatch_tables = | 160 Handle<FixedArray> new_dispatch_tables = |
| 150 isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3); | 161 isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3); |
| 151 | 162 |
| 152 new_dispatch_tables->set(dispatch_tables->length() + 0, *instance); | 163 new_dispatch_tables->set(dispatch_tables->length() + 0, *instance); |
| 153 new_dispatch_tables->set(dispatch_tables->length() + 1, | 164 new_dispatch_tables->set(dispatch_tables->length() + 1, |
| 154 Smi::FromInt(table_index)); | 165 Smi::FromInt(table_index)); |
| 155 new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table); | 166 new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table); |
| 156 | 167 |
| 157 table_obj->SetInternalField(WasmTableObject::kDispatchTables, | 168 table_obj->SetInternalField(WasmTableObject::kDispatchTables, |
| 158 *new_dispatch_tables); | 169 *new_dispatch_tables); |
| 159 | 170 |
| 160 return new_dispatch_tables; | 171 return new_dispatch_tables; |
| 161 } | 172 } |
| 162 | 173 |
| 163 DEFINE_ACCESSORS(WasmTableObject, functions, kFunctions, FixedArray) | 174 DEFINE_OBJ_ACCESSORS(WasmTableObject, functions, kFunctions, FixedArray) |
| 164 | 175 |
| 165 uint32_t WasmTableObject::current_length() { return get_functions()->length(); } | 176 uint32_t WasmTableObject::current_length() { return functions()->length(); } |
| 166 | 177 |
| 167 uint32_t WasmTableObject::maximum_length() { | 178 uint32_t WasmTableObject::maximum_length() { |
| 168 return SafeUint32(GetInternalField(kMaximum)); | 179 return SafeUint32(GetInternalField(kMaximum)); |
| 169 } | 180 } |
| 170 | 181 |
| 171 WasmTableObject* WasmTableObject::cast(Object* object) { | 182 WasmTableObject* WasmTableObject::cast(Object* object) { |
| 172 DCHECK(object && object->IsJSObject()); | 183 DCHECK(object && object->IsJSObject()); |
| 173 // TODO(titzer): brand check for WasmTableObject. | 184 // TODO(titzer): brand check for WasmTableObject. |
| 174 return reinterpret_cast<WasmTableObject*>(object); | 185 return reinterpret_cast<WasmTableObject*>(object); |
| 175 } | 186 } |
| 176 | 187 |
| 177 Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate, | 188 Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate, |
| 178 Handle<JSArrayBuffer> buffer, | 189 Handle<JSArrayBuffer> buffer, |
| 179 int maximum) { | 190 int maximum) { |
| 180 Handle<JSFunction> memory_ctor( | 191 Handle<JSFunction> memory_ctor( |
| 181 isolate->native_context()->wasm_memory_constructor()); | 192 isolate->native_context()->wasm_memory_constructor()); |
| 182 Handle<JSObject> memory_obj = | 193 Handle<JSObject> memory_obj = |
| 183 isolate->factory()->NewJSObject(memory_ctor, TENURED); | 194 isolate->factory()->NewJSObject(memory_ctor, TENURED); |
| 184 memory_obj->SetInternalField(kArrayBuffer, *buffer); | 195 memory_obj->SetInternalField(kArrayBuffer, *buffer); |
| 185 memory_obj->SetInternalField(kMaximum, | 196 memory_obj->SetInternalField(kMaximum, |
| 186 static_cast<Object*>(Smi::FromInt(maximum))); | 197 static_cast<Object*>(Smi::FromInt(maximum))); |
| 187 Handle<Symbol> memory_sym(isolate->native_context()->wasm_memory_sym()); | 198 Handle<Symbol> memory_sym(isolate->native_context()->wasm_memory_sym()); |
| 188 Object::SetProperty(memory_obj, memory_sym, memory_obj, STRICT).Check(); | 199 Object::SetProperty(memory_obj, memory_sym, memory_obj, STRICT).Check(); |
| 189 return Handle<WasmMemoryObject>::cast(memory_obj); | 200 return Handle<WasmMemoryObject>::cast(memory_obj); |
| 190 } | 201 } |
| 191 | 202 |
| 192 DEFINE_ACCESSORS(WasmMemoryObject, buffer, kArrayBuffer, JSArrayBuffer) | 203 DEFINE_OBJ_ACCESSORS(WasmMemoryObject, buffer, kArrayBuffer, JSArrayBuffer) |
| 193 DEFINE_OPTIONAL_ACCESSORS(WasmMemoryObject, instances_link, kInstancesLink, | 204 DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmMemoryObject, instances_link, kInstancesLink, |
| 194 WasmInstanceWrapper) | 205 WasmInstanceWrapper) |
| 195 | 206 |
| 196 uint32_t WasmMemoryObject::current_pages() { | 207 uint32_t WasmMemoryObject::current_pages() { |
| 197 return SafeUint32(get_buffer()->byte_length()) / wasm::WasmModule::kPageSize; | 208 return SafeUint32(buffer()->byte_length()) / wasm::WasmModule::kPageSize; |
| 198 } | 209 } |
| 199 | 210 |
| 200 int32_t WasmMemoryObject::maximum_pages() { | 211 int32_t WasmMemoryObject::maximum_pages() { |
| 201 return SafeInt32(GetInternalField(kMaximum)); | 212 return SafeInt32(GetInternalField(kMaximum)); |
| 202 } | 213 } |
| 203 | 214 |
| 204 WasmMemoryObject* WasmMemoryObject::cast(Object* object) { | 215 WasmMemoryObject* WasmMemoryObject::cast(Object* object) { |
| 205 DCHECK(object && object->IsJSObject()); | 216 DCHECK(object && object->IsJSObject()); |
| 206 // TODO(titzer): brand check for WasmMemoryObject. | 217 // TODO(titzer): brand check for WasmMemoryObject. |
| 207 return reinterpret_cast<WasmMemoryObject*>(object); | 218 return reinterpret_cast<WasmMemoryObject*>(object); |
| 208 } | 219 } |
| 209 | 220 |
| 210 void WasmMemoryObject::AddInstance(Isolate* isolate, | 221 void WasmMemoryObject::AddInstance(Isolate* isolate, |
| 211 Handle<WasmInstanceObject> instance) { | 222 Handle<WasmInstanceObject> instance) { |
| 212 Handle<WasmInstanceWrapper> instance_wrapper = | 223 Handle<WasmInstanceWrapper> instance_wrapper = |
| 213 handle(instance->get_instance_wrapper()); | 224 handle(instance->instance_wrapper()); |
| 214 if (has_instances_link()) { | 225 if (has_instances_link()) { |
| 215 Handle<WasmInstanceWrapper> current_wrapper(get_instances_link()); | 226 Handle<WasmInstanceWrapper> current_wrapper(instances_link()); |
| 216 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*current_wrapper)); | 227 DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*current_wrapper)); |
| 217 DCHECK(!current_wrapper->has_previous()); | 228 DCHECK(!current_wrapper->has_previous()); |
| 218 instance_wrapper->set_next_wrapper(*current_wrapper); | 229 instance_wrapper->set_next_wrapper(*current_wrapper); |
| 219 current_wrapper->set_previous_wrapper(*instance_wrapper); | 230 current_wrapper->set_previous_wrapper(*instance_wrapper); |
| 220 } | 231 } |
| 221 set_instances_link(*instance_wrapper); | 232 set_instances_link(*instance_wrapper); |
| 222 } | 233 } |
| 223 | 234 |
| 224 void WasmMemoryObject::ResetInstancesLink(Isolate* isolate) { | 235 void WasmMemoryObject::ResetInstancesLink(Isolate* isolate) { |
| 225 Handle<Object> undefined = isolate->factory()->undefined_value(); | 236 Handle<Object> undefined = isolate->factory()->undefined_value(); |
| 226 SetInternalField(kInstancesLink, *undefined); | 237 SetInternalField(kInstancesLink, *undefined); |
| 227 } | 238 } |
| 228 | 239 |
| 229 DEFINE_ACCESSORS(WasmInstanceObject, compiled_module, kCompiledModule, | 240 DEFINE_OBJ_ACCESSORS(WasmInstanceObject, compiled_module, kCompiledModule, |
| 230 WasmCompiledModule) | 241 WasmCompiledModule) |
| 231 DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, globals_buffer, | 242 DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, globals_buffer, |
| 232 kGlobalsArrayBuffer, JSArrayBuffer) | 243 kGlobalsArrayBuffer, JSArrayBuffer) |
| 233 DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, memory_buffer, kMemoryArrayBuffer, | 244 DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, memory_buffer, |
| 234 JSArrayBuffer) | 245 kMemoryArrayBuffer, JSArrayBuffer) |
| 235 DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, memory_object, kMemoryObject, | 246 DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, memory_object, kMemoryObject, |
| 236 WasmMemoryObject) | 247 WasmMemoryObject) |
| 237 DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, debug_info, kDebugInfo, | 248 DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, debug_info, kDebugInfo, |
| 238 WasmDebugInfo) | 249 WasmDebugInfo) |
| 239 DEFINE_OPTIONAL_ACCESSORS(WasmInstanceObject, instance_wrapper, | 250 DEFINE_OPTIONAL_OBJ_ACCESSORS(WasmInstanceObject, instance_wrapper, |
| 240 kWasmMemInstanceWrapper, WasmInstanceWrapper) | 251 kWasmMemInstanceWrapper, WasmInstanceWrapper) |
| 241 | 252 |
| 242 WasmModuleObject* WasmInstanceObject::module_object() { | 253 WasmModuleObject* WasmInstanceObject::module_object() { |
| 243 return WasmModuleObject::cast(*get_compiled_module()->wasm_module()); | 254 return *compiled_module()->wasm_module(); |
| 244 } | 255 } |
| 245 | 256 |
| 246 WasmModule* WasmInstanceObject::module() { | 257 WasmModule* WasmInstanceObject::module() { return compiled_module()->module(); } |
| 247 return reinterpret_cast<WasmModuleWrapper*>( | 258 |
| 248 *get_compiled_module()->module_wrapper()) | 259 Handle<WasmDebugInfo> WasmInstanceObject::GetOrCreateDebugInfo( |
| 249 ->get(); | 260 Handle<WasmInstanceObject> instance) { |
| 261 if (instance->has_debug_info()) return handle(instance->debug_info()); |
| 262 Handle<WasmDebugInfo> new_info = WasmDebugInfo::New(instance); |
| 263 instance->set_debug_info(*new_info); |
| 264 return new_info; |
| 250 } | 265 } |
| 251 | 266 |
| 252 WasmInstanceObject* WasmInstanceObject::cast(Object* object) { | 267 WasmInstanceObject* WasmInstanceObject::cast(Object* object) { |
| 253 DCHECK(IsWasmInstanceObject(object)); | 268 DCHECK(IsWasmInstanceObject(object)); |
| 254 return reinterpret_cast<WasmInstanceObject*>(object); | 269 return reinterpret_cast<WasmInstanceObject*>(object); |
| 255 } | 270 } |
| 256 | 271 |
| 257 bool WasmInstanceObject::IsWasmInstanceObject(Object* object) { | 272 bool WasmInstanceObject::IsWasmInstanceObject(Object* object) { |
| 258 if (!object->IsObject()) return false; | |
| 259 if (!object->IsJSObject()) return false; | 273 if (!object->IsJSObject()) return false; |
| 260 | 274 |
| 261 JSObject* obj = JSObject::cast(object); | 275 JSObject* obj = JSObject::cast(object); |
| 262 Isolate* isolate = obj->GetIsolate(); | 276 Isolate* isolate = obj->GetIsolate(); |
| 263 if (obj->GetInternalFieldCount() != kFieldCount) { | 277 if (obj->GetInternalFieldCount() != kFieldCount) { |
| 264 return false; | 278 return false; |
| 265 } | 279 } |
| 266 | 280 |
| 267 Object* mem = obj->GetInternalField(kMemoryArrayBuffer); | 281 Object* mem = obj->GetInternalField(kMemoryArrayBuffer); |
| 268 if (!(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) || | 282 if (!(mem->IsUndefined(isolate) || mem->IsJSArrayBuffer()) || |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 shared->set_internal_formal_parameter_count(arity); | 344 shared->set_internal_formal_parameter_count(arity); |
| 331 Handle<JSFunction> function = isolate->factory()->NewFunction( | 345 Handle<JSFunction> function = isolate->factory()->NewFunction( |
| 332 isolate->wasm_function_map(), name, export_wrapper); | 346 isolate->wasm_function_map(), name, export_wrapper); |
| 333 function->set_shared(*shared); | 347 function->set_shared(*shared); |
| 334 | 348 |
| 335 function->SetInternalField(kInstance, *instance); | 349 function->SetInternalField(kInstance, *instance); |
| 336 function->SetInternalField(kIndex, Smi::FromInt(func_index)); | 350 function->SetInternalField(kIndex, Smi::FromInt(func_index)); |
| 337 return Handle<WasmExportedFunction>::cast(function); | 351 return Handle<WasmExportedFunction>::cast(function); |
| 338 } | 352 } |
| 339 | 353 |
| 354 bool WasmSharedModuleData::IsWasmSharedModuleData(Object* object) { |
| 355 if (!object->IsFixedArray()) return false; |
| 356 FixedArray* arr = FixedArray::cast(object); |
| 357 if (arr->length() != kFieldCount) return false; |
| 358 Isolate* isolate = arr->GetIsolate(); |
| 359 if (!arr->get(kModuleWrapper)->IsForeign()) return false; |
| 360 if (!arr->get(kModuleBytes)->IsUndefined(isolate) && |
| 361 !arr->get(kModuleBytes)->IsSeqOneByteString()) |
| 362 return false; |
| 363 if (!arr->get(kScript)->IsScript()) return false; |
| 364 if (!arr->get(kAsmJsOffsetTable)->IsUndefined(isolate) && |
| 365 !arr->get(kAsmJsOffsetTable)->IsByteArray()) |
| 366 return false; |
| 367 return true; |
| 368 } |
| 369 |
| 370 WasmSharedModuleData* WasmSharedModuleData::cast(Object* object) { |
| 371 DCHECK(IsWasmSharedModuleData(object)); |
| 372 return reinterpret_cast<WasmSharedModuleData*>(object); |
| 373 } |
| 374 |
| 375 wasm::WasmModule* WasmSharedModuleData::module() { |
| 376 return reinterpret_cast<WasmModuleWrapper*>(get(kModuleWrapper))->get(); |
| 377 } |
| 378 |
| 379 DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, module_bytes, kModuleBytes, |
| 380 SeqOneByteString); |
| 381 DEFINE_ARR_GETTER(WasmSharedModuleData, script, kScript, Script); |
| 382 DEFINE_OPTIONAL_ARR_ACCESSORS(WasmSharedModuleData, asm_js_offset_table, |
| 383 kAsmJsOffsetTable, ByteArray); |
| 384 |
| 385 Handle<WasmSharedModuleData> WasmSharedModuleData::New( |
| 386 Isolate* isolate, Handle<Foreign> module_wrapper, |
| 387 Handle<SeqOneByteString> module_bytes, Handle<Script> script, |
| 388 Handle<ByteArray> asm_js_offset_table) { |
| 389 Handle<FixedArray> arr = |
| 390 isolate->factory()->NewFixedArray(kFieldCount, TENURED); |
| 391 |
| 392 arr->set(kModuleWrapper, *module_wrapper); |
| 393 if (!module_bytes.is_null()) { |
| 394 arr->set(kModuleBytes, *module_bytes); |
| 395 } |
| 396 if (!script.is_null()) { |
| 397 arr->set(kScript, *script); |
| 398 } |
| 399 if (!asm_js_offset_table.is_null()) { |
| 400 arr->set(kAsmJsOffsetTable, *asm_js_offset_table); |
| 401 } |
| 402 |
| 403 DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*arr)); |
| 404 return Handle<WasmSharedModuleData>::cast(arr); |
| 405 } |
| 406 |
| 407 bool WasmSharedModuleData::is_asm_js() { |
| 408 bool asm_js = module()->origin == wasm::ModuleOrigin::kAsmJsOrigin; |
| 409 DCHECK_EQ(asm_js, script()->type() == Script::TYPE_NORMAL); |
| 410 DCHECK_EQ(asm_js, has_asm_js_offset_table()); |
| 411 return asm_js; |
| 412 } |
| 413 |
| 414 void WasmSharedModuleData::RecreateModuleWrapper( |
| 415 Isolate* isolate, Handle<WasmSharedModuleData> shared) { |
| 416 DCHECK(shared->get(kModuleWrapper)->IsUndefined(isolate)); |
| 417 |
| 418 WasmModule* module = nullptr; |
| 419 { |
| 420 // We parse the module again directly from the module bytes, so |
| 421 // the underlying storage must not be moved meanwhile. |
| 422 DisallowHeapAllocation no_allocation; |
| 423 SeqOneByteString* module_bytes = shared->module_bytes(); |
| 424 const byte* start = |
| 425 reinterpret_cast<const byte*>(module_bytes->GetCharsAddress()); |
| 426 const byte* end = start + module_bytes->length(); |
| 427 // TODO(titzer): remember the module origin in the compiled_module |
| 428 // For now, we assume serialized modules did not originate from asm.js. |
| 429 ModuleResult result = |
| 430 DecodeWasmModule(isolate, start, end, false, kWasmOrigin); |
| 431 CHECK(result.ok()); |
| 432 CHECK_NOT_NULL(result.val); |
| 433 module = const_cast<WasmModule*>(result.val); |
| 434 } |
| 435 |
| 436 Handle<WasmModuleWrapper> module_wrapper = |
| 437 WasmModuleWrapper::New(isolate, module); |
| 438 |
| 439 shared->set(kModuleWrapper, *module_wrapper); |
| 440 DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
| 441 } |
| 442 |
| 340 Handle<WasmCompiledModule> WasmCompiledModule::New( | 443 Handle<WasmCompiledModule> WasmCompiledModule::New( |
| 341 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper) { | 444 Isolate* isolate, Handle<WasmSharedModuleData> shared) { |
| 342 Handle<FixedArray> ret = | 445 Handle<FixedArray> ret = |
| 343 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); | 446 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); |
| 344 // WasmCompiledModule::cast would fail since module bytes are not set yet. | 447 // WasmCompiledModule::cast would fail since fields are not set yet. |
| 345 Handle<WasmCompiledModule> compiled_module( | 448 Handle<WasmCompiledModule> compiled_module( |
| 346 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); | 449 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); |
| 347 compiled_module->InitId(); | 450 compiled_module->InitId(); |
| 348 compiled_module->set_module_wrapper(module_wrapper); | 451 compiled_module->set_shared(shared); |
| 349 return compiled_module; | 452 return compiled_module; |
| 350 } | 453 } |
| 351 | 454 |
| 352 wasm::WasmModule* WasmCompiledModule::module() const { | |
| 353 return reinterpret_cast<WasmModuleWrapper*>(ptr_to_module_wrapper())->get(); | |
| 354 } | |
| 355 | |
| 356 void WasmCompiledModule::InitId() { | 455 void WasmCompiledModule::InitId() { |
| 357 #if DEBUG | 456 #if DEBUG |
| 358 static uint32_t instance_id_counter = 0; | 457 static uint32_t instance_id_counter = 0; |
| 359 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); | 458 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); |
| 360 TRACE("New compiled module id: %d\n", instance_id()); | 459 TRACE("New compiled module id: %d\n", instance_id()); |
| 361 #endif | 460 #endif |
| 362 } | 461 } |
| 363 | 462 |
| 364 MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes( | 463 MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes( |
| 365 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, | 464 Isolate* isolate, Handle<WasmCompiledModule> compiled_module, |
| 366 uint32_t offset, uint32_t size) { | 465 uint32_t offset, uint32_t size) { |
| 367 // TODO(wasm): cache strings from modules if it's a performance win. | 466 // TODO(wasm): cache strings from modules if it's a performance win. |
| 368 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | 467 Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(), |
| 468 isolate); |
| 369 DCHECK_GE(module_bytes->length(), offset); | 469 DCHECK_GE(module_bytes->length(), offset); |
| 370 DCHECK_GE(module_bytes->length() - offset, size); | 470 DCHECK_GE(module_bytes->length() - offset, size); |
| 371 Address raw = module_bytes->GetCharsAddress() + offset; | 471 Address raw = module_bytes->GetCharsAddress() + offset; |
| 372 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) | 472 if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size)) |
| 373 return {}; // UTF8 decoding error for name. | 473 return {}; // UTF8 decoding error for name. |
| 374 DCHECK_GE(kMaxInt, offset); | 474 DCHECK_GE(kMaxInt, offset); |
| 375 DCHECK_GE(kMaxInt, size); | 475 DCHECK_GE(kMaxInt, size); |
| 376 return isolate->factory()->NewStringFromUtf8SubString( | 476 return isolate->factory()->NewStringFromUtf8SubString( |
| 377 module_bytes, static_cast<int>(offset), static_cast<int>(size)); | 477 module_bytes, static_cast<int>(offset), static_cast<int>(size)); |
| 378 } | 478 } |
| 379 | 479 |
| 380 bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) { | 480 bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) { |
| 381 if (!obj->IsFixedArray()) return false; | 481 if (!obj->IsFixedArray()) return false; |
| 382 FixedArray* arr = FixedArray::cast(obj); | 482 FixedArray* arr = FixedArray::cast(obj); |
| 383 if (arr->length() != PropertyIndices::Count) return false; | 483 if (arr->length() != PropertyIndices::Count) return false; |
| 384 Isolate* isolate = arr->GetIsolate(); | 484 Isolate* isolate = arr->GetIsolate(); |
| 385 #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \ | 485 #define WCM_CHECK_TYPE(NAME, TYPE_CHECK) \ |
| 386 if (!arr->get(kID_##NAME)->IsSmi()) return false; | 486 do { \ |
| 387 #define WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME) \ | 487 Object* obj = arr->get(kID_##NAME); \ |
| 388 if (!arr->get(kID_##NAME)->IsUndefined(isolate) && \ | 488 if (!(TYPE_CHECK)) return false; \ |
| 389 !arr->get(kID_##NAME)->Is##TYPE()) \ | 489 } while (false); |
| 390 return false; | 490 #define WCM_CHECK_OBJECT(TYPE, NAME) \ |
| 391 #define WCM_CHECK_OBJECT(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME) | 491 WCM_CHECK_TYPE(NAME, obj->IsUndefined(isolate) || obj->Is##TYPE()) |
| 392 #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(WeakCell, NAME) | 492 #define WCM_CHECK_WASM_OBJECT(TYPE, NAME) \ |
| 493 WCM_CHECK_TYPE(NAME, TYPE::Is##TYPE(obj)) |
| 494 #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT(WeakCell, NAME) |
| 495 #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) WCM_CHECK_TYPE(NAME, obj->IsSmi()) |
| 393 #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME) | 496 #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME) |
| 394 WCM_PROPERTY_TABLE(WCM_CHECK) | 497 WCM_PROPERTY_TABLE(WCM_CHECK) |
| 395 #undef WCM_CHECK | 498 #undef WCM_CHECK |
| 396 | 499 |
| 397 // All checks passed. | 500 // All checks passed. |
| 398 return true; | 501 return true; |
| 399 } | 502 } |
| 400 | 503 |
| 401 void WasmCompiledModule::PrintInstancesChain() { | 504 void WasmCompiledModule::PrintInstancesChain() { |
| 402 #if DEBUG | 505 #if DEBUG |
| 403 if (!FLAG_trace_wasm_instances) return; | 506 if (!FLAG_trace_wasm_instances) return; |
| 404 for (WasmCompiledModule* current = this; current != nullptr;) { | 507 for (WasmCompiledModule* current = this; current != nullptr;) { |
| 405 PrintF("->%d", current->instance_id()); | 508 PrintF("->%d", current->instance_id()); |
| 406 if (!current->has_weak_next_instance()) break; | 509 if (!current->has_weak_next_instance()) break; |
| 407 CHECK(!current->ptr_to_weak_next_instance()->cleared()); | 510 CHECK(!current->ptr_to_weak_next_instance()->cleared()); |
| 408 current = | 511 current = |
| 409 WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value()); | 512 WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value()); |
| 410 } | 513 } |
| 411 PrintF("\n"); | 514 PrintF("\n"); |
| 412 #endif | 515 #endif |
| 413 } | 516 } |
| 414 | 517 |
| 415 void WasmCompiledModule::RecreateModuleWrapper(Isolate* isolate, | 518 void WasmCompiledModule::RecreateModuleWrapper( |
| 416 Handle<FixedArray> array) { | 519 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { |
| 417 Handle<WasmCompiledModule> compiled_module( | 520 // This method must only be called immediately after deserialization. |
| 418 reinterpret_cast<WasmCompiledModule*>(*array), isolate); | 521 // At this point, no module wrapper exists, so the shared module data is |
| 419 | 522 // incomplete. |
| 420 WasmModule* module = nullptr; | 523 Handle<WasmSharedModuleData> shared( |
| 421 { | 524 static_cast<WasmSharedModuleData*>(compiled_module->get(kID_shared)), |
| 422 Handle<SeqOneByteString> module_bytes = compiled_module->module_bytes(); | 525 isolate); |
| 423 // We parse the module again directly from the module bytes, so | 526 DCHECK(!WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
| 424 // the underlying storage must not be moved meanwhile. | 527 WasmSharedModuleData::RecreateModuleWrapper(isolate, shared); |
| 425 DisallowHeapAllocation no_allocation; | 528 DCHECK(WasmSharedModuleData::IsWasmSharedModuleData(*shared)); |
| 426 const byte* start = | |
| 427 reinterpret_cast<const byte*>(module_bytes->GetCharsAddress()); | |
| 428 const byte* end = start + module_bytes->length(); | |
| 429 // TODO(titzer): remember the module origin in the compiled_module | |
| 430 // For now, we assume serialized modules did not originate from asm.js. | |
| 431 ModuleResult result = | |
| 432 DecodeWasmModule(isolate, start, end, false, kWasmOrigin); | |
| 433 CHECK(result.ok()); | |
| 434 CHECK_NOT_NULL(result.val); | |
| 435 module = const_cast<WasmModule*>(result.val); | |
| 436 } | |
| 437 | |
| 438 Handle<WasmModuleWrapper> module_wrapper = | |
| 439 WasmModuleWrapper::New(isolate, module); | |
| 440 | |
| 441 compiled_module->set_module_wrapper(module_wrapper); | |
| 442 DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); | |
| 443 } | 529 } |
| 444 | 530 |
| 445 uint32_t WasmCompiledModule::mem_size() const { | 531 uint32_t WasmCompiledModule::mem_size() const { |
| 446 return has_memory() ? memory()->byte_length()->Number() : default_mem_size(); | 532 return has_memory() ? memory()->byte_length()->Number() : default_mem_size(); |
| 447 } | 533 } |
| 448 | 534 |
| 449 uint32_t WasmCompiledModule::default_mem_size() const { | 535 uint32_t WasmCompiledModule::default_mem_size() const { |
| 450 return min_mem_pages() * WasmModule::kPageSize; | 536 return min_mem_pages() * WasmModule::kPageSize; |
| 451 } | 537 } |
| 452 | 538 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 465 MaybeHandle<String> name = | 551 MaybeHandle<String> name = |
| 466 GetFunctionNameOrNull(isolate, compiled_module, func_index); | 552 GetFunctionNameOrNull(isolate, compiled_module, func_index); |
| 467 if (!name.is_null()) return name.ToHandleChecked(); | 553 if (!name.is_null()) return name.ToHandleChecked(); |
| 468 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); | 554 return isolate->factory()->NewStringFromStaticChars("<WASM UNNAMED>"); |
| 469 } | 555 } |
| 470 | 556 |
| 471 Vector<const uint8_t> WasmCompiledModule::GetRawFunctionName( | 557 Vector<const uint8_t> WasmCompiledModule::GetRawFunctionName( |
| 472 uint32_t func_index) { | 558 uint32_t func_index) { |
| 473 DCHECK_GT(module()->functions.size(), func_index); | 559 DCHECK_GT(module()->functions.size(), func_index); |
| 474 WasmFunction& function = module()->functions[func_index]; | 560 WasmFunction& function = module()->functions[func_index]; |
| 475 SeqOneByteString* bytes = ptr_to_module_bytes(); | 561 SeqOneByteString* bytes = module_bytes(); |
| 476 DCHECK_GE(bytes->length(), function.name_offset); | 562 DCHECK_GE(bytes->length(), function.name_offset); |
| 477 DCHECK_GE(bytes->length() - function.name_offset, function.name_length); | 563 DCHECK_GE(bytes->length() - function.name_offset, function.name_length); |
| 478 return Vector<const uint8_t>(bytes->GetCharsAddress() + function.name_offset, | 564 return Vector<const uint8_t>(bytes->GetCharsAddress() + function.name_offset, |
| 479 function.name_length); | 565 function.name_length); |
| 480 } | 566 } |
| 481 | 567 |
| 482 int WasmCompiledModule::GetFunctionOffset(uint32_t func_index) const { | 568 int WasmCompiledModule::GetFunctionOffset(uint32_t func_index) { |
| 483 std::vector<WasmFunction>& functions = module()->functions; | 569 std::vector<WasmFunction>& functions = module()->functions; |
| 484 if (static_cast<uint32_t>(func_index) >= functions.size()) return -1; | 570 if (static_cast<uint32_t>(func_index) >= functions.size()) return -1; |
| 485 DCHECK_GE(kMaxInt, functions[func_index].code_start_offset); | 571 DCHECK_GE(kMaxInt, functions[func_index].code_start_offset); |
| 486 return static_cast<int>(functions[func_index].code_start_offset); | 572 return static_cast<int>(functions[func_index].code_start_offset); |
| 487 } | 573 } |
| 488 | 574 |
| 489 int WasmCompiledModule::GetContainingFunction(uint32_t byte_offset) const { | 575 int WasmCompiledModule::GetContainingFunction(uint32_t byte_offset) { |
| 490 std::vector<WasmFunction>& functions = module()->functions; | 576 std::vector<WasmFunction>& functions = module()->functions; |
| 491 | 577 |
| 492 // Binary search for a function containing the given position. | 578 // Binary search for a function containing the given position. |
| 493 int left = 0; // inclusive | 579 int left = 0; // inclusive |
| 494 int right = static_cast<int>(functions.size()); // exclusive | 580 int right = static_cast<int>(functions.size()); // exclusive |
| 495 if (right == 0) return false; | 581 if (right == 0) return false; |
| 496 while (right - left > 1) { | 582 while (right - left > 1) { |
| 497 int mid = left + (right - left) / 2; | 583 int mid = left + (right - left) / 2; |
| 498 if (functions[mid].code_start_offset <= byte_offset) { | 584 if (functions[mid].code_start_offset <= byte_offset) { |
| 499 left = mid; | 585 left = mid; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 529 | 615 |
| 530 enum AsmJsOffsetTableEntryLayout { | 616 enum AsmJsOffsetTableEntryLayout { |
| 531 kOTEByteOffset, | 617 kOTEByteOffset, |
| 532 kOTECallPosition, | 618 kOTECallPosition, |
| 533 kOTENumberConvPosition, | 619 kOTENumberConvPosition, |
| 534 kOTESize | 620 kOTESize |
| 535 }; | 621 }; |
| 536 | 622 |
| 537 Handle<ByteArray> GetDecodedAsmJsOffsetTable( | 623 Handle<ByteArray> GetDecodedAsmJsOffsetTable( |
| 538 Handle<WasmCompiledModule> compiled_module, Isolate* isolate) { | 624 Handle<WasmCompiledModule> compiled_module, Isolate* isolate) { |
| 539 DCHECK(compiled_module->has_asm_js_offset_table()); | 625 DCHECK(compiled_module->is_asm_js()); |
| 540 Handle<ByteArray> offset_table = compiled_module->asm_js_offset_table(); | 626 Handle<ByteArray> offset_table( |
| 627 compiled_module->shared()->asm_js_offset_table(), isolate); |
| 541 | 628 |
| 542 // The last byte in the asm_js_offset_tables ByteArray tells whether it is | 629 // The last byte in the asm_js_offset_tables ByteArray tells whether it is |
| 543 // still encoded (0) or decoded (1). | 630 // still encoded (0) or decoded (1). |
| 544 enum AsmJsTableType : int { Encoded = 0, Decoded = 1 }; | 631 enum AsmJsTableType : int { Encoded = 0, Decoded = 1 }; |
| 545 int table_type = offset_table->get(offset_table->length() - 1); | 632 int table_type = offset_table->get(offset_table->length() - 1); |
| 546 DCHECK(table_type == Encoded || table_type == Decoded); | 633 DCHECK(table_type == Encoded || table_type == Decoded); |
| 547 if (table_type == Decoded) return offset_table; | 634 if (table_type == Decoded) return offset_table; |
| 548 | 635 |
| 549 AsmJsOffsetsResult asm_offsets; | 636 AsmJsOffsetsResult asm_offsets; |
| 550 { | 637 { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 567 DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries); | 654 DCHECK_LE(new_size, static_cast<size_t>(kMaxInt) - num_entries); |
| 568 num_entries += static_cast<int>(new_size); | 655 num_entries += static_cast<int>(new_size); |
| 569 } | 656 } |
| 570 // One byte to encode that this is a decoded table. | 657 // One byte to encode that this is a decoded table. |
| 571 DCHECK_GE(kMaxInt, | 658 DCHECK_GE(kMaxInt, |
| 572 1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize); | 659 1 + static_cast<uint64_t>(num_entries) * kOTESize * kIntSize); |
| 573 int total_size = 1 + num_entries * kOTESize * kIntSize; | 660 int total_size = 1 + num_entries * kOTESize * kIntSize; |
| 574 Handle<ByteArray> decoded_table = | 661 Handle<ByteArray> decoded_table = |
| 575 isolate->factory()->NewByteArray(total_size, TENURED); | 662 isolate->factory()->NewByteArray(total_size, TENURED); |
| 576 decoded_table->set(total_size - 1, AsmJsTableType::Decoded); | 663 decoded_table->set(total_size - 1, AsmJsTableType::Decoded); |
| 577 compiled_module->set_asm_js_offset_table(decoded_table); | 664 compiled_module->shared()->set_asm_js_offset_table(*decoded_table); |
| 578 | 665 |
| 579 int idx = 0; | 666 int idx = 0; |
| 580 std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions; | 667 std::vector<WasmFunction>& wasm_funs = compiled_module->module()->functions; |
| 581 for (int func = 0; func < num_functions; ++func) { | 668 for (int func = 0; func < num_functions; ++func) { |
| 582 std::vector<AsmJsOffsetEntry>& func_asm_offsets = asm_offsets.val[func]; | 669 std::vector<AsmJsOffsetEntry>& func_asm_offsets = asm_offsets.val[func]; |
| 583 if (func_asm_offsets.empty()) continue; | 670 if (func_asm_offsets.empty()) continue; |
| 584 int func_offset = | 671 int func_offset = |
| 585 wasm_funs[num_imported_functions + func].code_start_offset; | 672 wasm_funs[num_imported_functions + func].code_start_offset; |
| 586 for (AsmJsOffsetEntry& e : func_asm_offsets) { | 673 for (AsmJsOffsetEntry& e : func_asm_offsets) { |
| 587 // Byte offsets must be strictly monotonously increasing: | 674 // Byte offsets must be strictly monotonously increasing: |
| 588 DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset > | 675 DCHECK_IMPLIES(idx > 0, func_offset + e.byte_offset > |
| 589 decoded_table->get_int(idx - kOTESize)); | 676 decoded_table->get_int(idx - kOTESize)); |
| 590 decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset); | 677 decoded_table->set_int(idx + kOTEByteOffset, func_offset + e.byte_offset); |
| 591 decoded_table->set_int(idx + kOTECallPosition, e.source_position_call); | 678 decoded_table->set_int(idx + kOTECallPosition, e.source_position_call); |
| 592 decoded_table->set_int(idx + kOTENumberConvPosition, | 679 decoded_table->set_int(idx + kOTENumberConvPosition, |
| 593 e.source_position_number_conversion); | 680 e.source_position_number_conversion); |
| 594 idx += kOTESize; | 681 idx += kOTESize; |
| 595 } | 682 } |
| 596 } | 683 } |
| 597 DCHECK_EQ(total_size, idx * kIntSize + 1); | 684 DCHECK_EQ(total_size, idx * kIntSize + 1); |
| 598 return decoded_table; | 685 return decoded_table; |
| 599 } | 686 } |
| 687 |
| 600 } // namespace | 688 } // namespace |
| 601 | 689 |
| 602 int WasmCompiledModule::GetAsmJsSourcePosition( | 690 int WasmCompiledModule::GetAsmJsSourcePosition( |
| 603 Handle<WasmCompiledModule> compiled_module, uint32_t func_index, | 691 Handle<WasmCompiledModule> compiled_module, uint32_t func_index, |
| 604 uint32_t byte_offset, bool is_at_number_conversion) { | 692 uint32_t byte_offset, bool is_at_number_conversion) { |
| 605 Isolate* isolate = compiled_module->GetIsolate(); | 693 Isolate* isolate = compiled_module->GetIsolate(); |
| 606 Handle<ByteArray> offset_table = | 694 Handle<ByteArray> offset_table = |
| 607 GetDecodedAsmJsOffsetTable(compiled_module, isolate); | 695 GetDecodedAsmJsOffsetTable(compiled_module, isolate); |
| 608 | 696 |
| 609 DCHECK_LT(func_index, compiled_module->module()->functions.size()); | 697 DCHECK_LT(func_index, compiled_module->module()->functions.size()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 633 } | 721 } |
| 634 | 722 |
| 635 v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction( | 723 v8::debug::WasmDisassembly WasmCompiledModule::DisassembleFunction( |
| 636 int func_index) { | 724 int func_index) { |
| 637 DisallowHeapAllocation no_gc; | 725 DisallowHeapAllocation no_gc; |
| 638 | 726 |
| 639 if (func_index < 0 || | 727 if (func_index < 0 || |
| 640 static_cast<uint32_t>(func_index) >= module()->functions.size()) | 728 static_cast<uint32_t>(func_index) >= module()->functions.size()) |
| 641 return {}; | 729 return {}; |
| 642 | 730 |
| 643 SeqOneByteString* module_bytes_str = ptr_to_module_bytes(); | 731 SeqOneByteString* module_bytes_str = module_bytes(); |
| 644 Vector<const byte> module_bytes(module_bytes_str->GetChars(), | 732 Vector<const byte> module_bytes(module_bytes_str->GetChars(), |
| 645 module_bytes_str->length()); | 733 module_bytes_str->length()); |
| 646 | 734 |
| 647 std::ostringstream disassembly_os; | 735 std::ostringstream disassembly_os; |
| 648 v8::debug::WasmDisassembly::OffsetTable offset_table; | 736 v8::debug::WasmDisassembly::OffsetTable offset_table; |
| 649 | 737 |
| 650 PrintWasmText(module(), module_bytes, static_cast<uint32_t>(func_index), | 738 PrintWasmText(module(), module_bytes, static_cast<uint32_t>(func_index), |
| 651 disassembly_os, &offset_table); | 739 disassembly_os, &offset_table); |
| 652 | 740 |
| 653 return {disassembly_os.str(), std::move(offset_table)}; | 741 return {disassembly_os.str(), std::move(offset_table)}; |
| 654 } | 742 } |
| 655 | 743 |
| 656 bool WasmCompiledModule::GetPossibleBreakpoints( | 744 bool WasmCompiledModule::GetPossibleBreakpoints( |
| 657 const v8::debug::Location& start, const v8::debug::Location& end, | 745 const v8::debug::Location& start, const v8::debug::Location& end, |
| 658 std::vector<v8::debug::Location>* locations) const { | 746 std::vector<v8::debug::Location>* locations) { |
| 659 DisallowHeapAllocation no_gc; | 747 DisallowHeapAllocation no_gc; |
| 660 | 748 |
| 661 std::vector<WasmFunction>& functions = module()->functions; | 749 std::vector<WasmFunction>& functions = module()->functions; |
| 662 if (start.GetLineNumber() < 0 || start.GetColumnNumber() < 0 || | 750 if (start.GetLineNumber() < 0 || start.GetColumnNumber() < 0 || |
| 663 (!end.IsEmpty() && | 751 (!end.IsEmpty() && |
| 664 (end.GetLineNumber() < 0 || end.GetColumnNumber() < 0))) | 752 (end.GetLineNumber() < 0 || end.GetColumnNumber() < 0))) |
| 665 return false; | 753 return false; |
| 666 | 754 |
| 667 // start_func_index, start_offset and end_func_index is inclusive. | 755 // start_func_index, start_offset and end_func_index is inclusive. |
| 668 // end_offset is exclusive. | 756 // end_offset is exclusive. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 693 } else { | 781 } else { |
| 694 if (end_func_index >= functions.size()) return false; | 782 if (end_func_index >= functions.size()) return false; |
| 695 end_offset = | 783 end_offset = |
| 696 functions[end_func_index].code_start_offset + end.GetColumnNumber(); | 784 functions[end_func_index].code_start_offset + end.GetColumnNumber(); |
| 697 if (end_offset > functions[end_func_index].code_end_offset) return false; | 785 if (end_offset > functions[end_func_index].code_end_offset) return false; |
| 698 } | 786 } |
| 699 } | 787 } |
| 700 | 788 |
| 701 AccountingAllocator alloc; | 789 AccountingAllocator alloc; |
| 702 Zone tmp(&alloc, ZONE_NAME); | 790 Zone tmp(&alloc, ZONE_NAME); |
| 703 const byte* module_start = ptr_to_module_bytes()->GetChars(); | 791 const byte* module_start = module_bytes()->GetChars(); |
| 704 | 792 |
| 705 for (uint32_t func_idx = start_func_index; func_idx <= end_func_index; | 793 for (uint32_t func_idx = start_func_index; func_idx <= end_func_index; |
| 706 ++func_idx) { | 794 ++func_idx) { |
| 707 WasmFunction& func = functions[func_idx]; | 795 WasmFunction& func = functions[func_idx]; |
| 708 if (func.code_start_offset == func.code_end_offset) continue; | 796 if (func.code_start_offset == func.code_end_offset) continue; |
| 709 | 797 |
| 710 AstLocalDecls locals(&tmp); | 798 AstLocalDecls locals(&tmp); |
| 711 BytecodeIterator iterator(module_start + func.code_start_offset, | 799 BytecodeIterator iterator(module_start + func.code_start_offset, |
| 712 module_start + func.code_end_offset, &locals); | 800 module_start + func.code_end_offset, &locals); |
| 713 DCHECK_LT(0u, locals.decls_encoded_size); | 801 DCHECK_LT(0u, locals.decls_encoded_size); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) | 835 !array->get(kPreviousInstanceWrapper)->IsFixedArray()) |
| 748 return false; | 836 return false; |
| 749 return true; | 837 return true; |
| 750 } | 838 } |
| 751 | 839 |
| 752 void WasmInstanceWrapper::set_instance_object(Handle<JSObject> instance, | 840 void WasmInstanceWrapper::set_instance_object(Handle<JSObject> instance, |
| 753 Isolate* isolate) { | 841 Isolate* isolate) { |
| 754 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); | 842 Handle<WeakCell> cell = isolate->factory()->NewWeakCell(instance); |
| 755 set(kWrapperInstanceObject, *cell); | 843 set(kWrapperInstanceObject, *cell); |
| 756 } | 844 } |
| OLD | NEW |