Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/wasm/wasm-objects.h" | |
| 6 #include "src/wasm/wasm-module.h" | |
| 7 | |
| 8 #define TRACE(...) \ | |
| 9 do { \ | |
| 10 if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \ | |
| 11 } while (false) | |
| 12 | |
| 13 #define TRACE_CHAIN(instance) \ | |
| 14 do { \ | |
| 15 instance->PrintInstancesChain(); \ | |
| 16 } while (false) | |
| 17 | |
| 18 using namespace v8::internal; | |
| 19 using namespace v8::internal::wasm; | |
| 20 | |
| 21 /* | |
| 22 static bool HasBrand(Isolate* isolate, Handle<Object> value, | |
| 23 Handle<Symbol> sym) { | |
| 24 if (value->IsJSObject()) { | |
| 25 Handle<JSObject> object = Handle<JSObject>::cast(value); | |
| 26 v8::Maybe<bool> has_brand = JSObject::HasOwnProperty(object, sym); | |
| 27 if (has_brand.IsNothing()) return false; | |
| 28 if (has_brand.ToChecked()) return true; | |
| 29 } | |
| 30 return false; | |
| 31 } | |
| 32 */ | |
| 33 | |
| 34 static uint32_t SafeUint32(Object* value) { | |
| 35 if (value->IsSmi()) { | |
| 36 int32_t val = Smi::cast(value)->value(); | |
| 37 CHECK_GE(val, 0); | |
| 38 return static_cast<uint32_t>(val); | |
| 39 } | |
| 40 DCHECK(value->IsHeapNumber()); | |
| 41 HeapNumber* num = HeapNumber::cast(value); | |
| 42 CHECK_GE(num->value(), 0.0); | |
| 43 CHECK_LE(num->value(), static_cast<double>(kMaxUInt32)); | |
| 44 return static_cast<uint32_t>(num->value()); | |
| 45 } | |
| 46 | |
| 47 static int32_t SafeInt32(Object* value) { | |
| 48 if (value->IsSmi()) { | |
| 49 return Smi::cast(value)->value(); | |
| 50 } | |
| 51 DCHECK(value->IsHeapNumber()); | |
| 52 HeapNumber* num = HeapNumber::cast(value); | |
| 53 CHECK_GE(num->value(), static_cast<double>(Smi::kMinValue)); | |
| 54 CHECK_LE(num->value(), static_cast<double>(Smi::kMaxValue)); | |
| 55 return static_cast<int32_t>(num->value()); | |
| 56 } | |
| 57 | |
| 58 Handle<WasmModuleObject> WasmModuleObject::New( | |
| 59 Isolate* isolate, Handle<WasmCompiledModule> compiled_module) { | |
| 60 ModuleOrigin origin = compiled_module->module()->origin; | |
| 61 | |
| 62 Handle<JSObject> wasm_module; | |
| 63 if (origin == ModuleOrigin::kWasmOrigin) { | |
| 64 Handle<JSFunction> module_cons( | |
| 65 isolate->native_context()->wasm_module_constructor()); | |
| 66 wasm_module = isolate->factory()->NewJSObject(module_cons); | |
| 67 } else { | |
| 68 DCHECK(origin == ModuleOrigin::kAsmJsOrigin); | |
| 69 Handle<Map> map = isolate->factory()->NewMap( | |
| 70 JS_OBJECT_TYPE, | |
| 71 JSObject::kHeaderSize + WasmModuleObject::kFieldCount * kPointerSize); | |
| 72 wasm_module = isolate->factory()->NewJSObjectFromMap(map, TENURED); | |
| 73 } | |
| 74 wasm_module->SetInternalField(WasmModuleObject::kCompiledModule, | |
| 75 *compiled_module); | |
| 76 if (origin == ModuleOrigin::kWasmOrigin) { | |
|
ahaas
2016/11/10 09:51:14
I think the code would be more readable if this {i
titzer
2016/11/10 10:33:25
Done.
| |
| 77 Handle<Symbol> module_sym(isolate->native_context()->wasm_module_sym()); | |
| 78 Object::SetProperty(wasm_module, module_sym, wasm_module, STRICT).Check(); | |
| 79 } | |
| 80 Handle<WeakCell> link_to_module = | |
| 81 isolate->factory()->NewWeakCell(wasm_module); | |
| 82 compiled_module->set_weak_wasm_module(link_to_module); | |
| 83 return Handle<WasmModuleObject>::cast(wasm_module); | |
| 84 } | |
| 85 | |
| 86 WasmModuleObject* WasmModuleObject::cast(Object* object) { | |
| 87 DCHECK(object->IsJSObject()); | |
| 88 // TODO(titzer): brand check for WasmModuleObject. | |
| 89 return reinterpret_cast<WasmModuleObject*>(object); | |
| 90 } | |
| 91 | |
| 92 Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, uint32_t initial, | |
| 93 bool has_maximum, uint32_t maximum, | |
| 94 Handle<FixedArray>* js_functions) { | |
| 95 Handle<JSFunction> table_ctor( | |
| 96 isolate->native_context()->wasm_table_constructor()); | |
| 97 Handle<JSObject> table_obj = isolate->factory()->NewJSObject(table_ctor); | |
| 98 *js_functions = isolate->factory()->NewFixedArray(initial); | |
| 99 Object* null = isolate->heap()->null_value(); | |
| 100 for (int i = 0; i < static_cast<int>(initial); ++i) { | |
| 101 (*js_functions)->set(i, null); | |
| 102 } | |
| 103 table_obj->SetInternalField(WasmTableObject::kArray, *(*js_functions)); | |
|
ahaas
2016/11/10 09:51:14
Is there a reason why the field is called {WasmTab
titzer
2016/11/10 10:33:25
Done.
| |
| 104 table_obj->SetInternalField( | |
| 105 WasmTableObject::kMaximum, | |
| 106 has_maximum ? static_cast<Object*>(Smi::FromInt(maximum)) | |
| 107 : static_cast<Object*>(isolate->heap()->undefined_value())); | |
| 108 Handle<FixedArray> dispatch_tables = isolate->factory()->NewFixedArray(0); | |
| 109 table_obj->SetInternalField(WasmTableObject::kDispatchTables, | |
| 110 *dispatch_tables); | |
| 111 Handle<Symbol> table_sym(isolate->native_context()->wasm_table_sym()); | |
| 112 Object::SetProperty(table_obj, table_sym, table_obj, STRICT).Check(); | |
| 113 return Handle<WasmTableObject>::cast(table_obj); | |
| 114 } | |
| 115 | |
| 116 Handle<FixedArray> WasmTableObject::AddDispatchTable( | |
| 117 Isolate* isolate, Handle<WasmTableObject> table_obj, | |
| 118 Handle<WasmInstanceObject> instance, int table_index, | |
| 119 Handle<FixedArray> dispatch_table) { | |
| 120 Handle<FixedArray> dispatch_tables( | |
| 121 FixedArray::cast(table_obj->GetInternalField(kDispatchTables)), isolate); | |
| 122 DCHECK_EQ(0, dispatch_tables->length() % 3); | |
| 123 | |
| 124 if (instance.is_null()) return dispatch_tables; | |
| 125 // TODO(titzer): use weak cells here to avoid leaking instances. | |
| 126 | |
| 127 // Grow the dispatch table and add a new triple at the end. | |
| 128 Handle<FixedArray> new_dispatch_tables = | |
| 129 isolate->factory()->CopyFixedArrayAndGrow(dispatch_tables, 3); | |
| 130 | |
| 131 new_dispatch_tables->set(dispatch_tables->length() + 0, *instance); | |
| 132 new_dispatch_tables->set(dispatch_tables->length() + 1, | |
| 133 Smi::FromInt(table_index)); | |
| 134 new_dispatch_tables->set(dispatch_tables->length() + 2, *dispatch_table); | |
| 135 | |
| 136 table_obj->SetInternalField(WasmTableObject::kDispatchTables, | |
| 137 *new_dispatch_tables); | |
| 138 | |
| 139 return new_dispatch_tables; | |
| 140 } | |
| 141 WasmTableObject* WasmTableObject::cast(Object* object) { | |
|
ahaas
2016/11/10 09:51:14
a newline is missing here.
titzer
2016/11/10 10:33:24
Done.
| |
| 142 DCHECK(object->IsJSObject()); | |
|
ahaas
2016/11/10 09:51:13
I think the DCHECK will crash if object is nullptr
titzer
2016/11/10 10:33:24
Done.
| |
| 143 // TODO(titzer): brand check for WasmTableObject. | |
| 144 return reinterpret_cast<WasmTableObject*>(object); | |
| 145 } | |
| 146 | |
| 147 Handle<WasmMemoryObject> WasmMemoryObject::New(Isolate* isolate, | |
| 148 Handle<JSArrayBuffer> buffer, | |
| 149 int maximum) { | |
| 150 Handle<JSFunction> memory_ctor( | |
| 151 isolate->native_context()->wasm_memory_constructor()); | |
| 152 Handle<JSObject> memory_obj = isolate->factory()->NewJSObject(memory_ctor); | |
| 153 memory_obj->SetInternalField(kArrayBuffer, *buffer); | |
| 154 memory_obj->SetInternalField(kMaximum, | |
| 155 static_cast<Object*>(Smi::FromInt(maximum))); | |
| 156 Handle<Symbol> memory_sym(isolate->native_context()->wasm_memory_sym()); | |
| 157 Object::SetProperty(memory_obj, memory_sym, memory_obj, STRICT).Check(); | |
| 158 return Handle<WasmMemoryObject>::cast(memory_obj); | |
| 159 } | |
| 160 | |
| 161 JSArrayBuffer* WasmMemoryObject::get_buffer() { | |
| 162 return JSArrayBuffer::cast(GetInternalField(kArrayBuffer)); | |
| 163 } | |
| 164 | |
| 165 void WasmMemoryObject::set_buffer(JSArrayBuffer* buffer) { | |
| 166 SetInternalField(kArrayBuffer, buffer); | |
| 167 } | |
| 168 | |
| 169 uint32_t WasmMemoryObject::current_pages() { | |
| 170 return SafeUint32(get_buffer()->byte_length()) / wasm::WasmModule::kPageSize; | |
| 171 } | |
| 172 | |
| 173 int32_t WasmMemoryObject::maximum_pages() { | |
| 174 return SafeInt32(GetInternalField(kMaximum)); | |
| 175 } | |
| 176 | |
| 177 WasmMemoryObject* WasmMemoryObject::cast(Object* object) { | |
| 178 DCHECK(object->IsJSObject()); | |
|
ahaas
2016/11/10 09:51:14
same here
titzer
2016/11/10 10:33:25
Done.
| |
| 179 // TODO(titzer): brand check for WasmMemoryObject. | |
| 180 return reinterpret_cast<WasmMemoryObject*>(object); | |
| 181 } | |
| 182 | |
| 183 WasmInstanceObject* WasmInstanceObject::cast(Object* object) { | |
| 184 DCHECK(IsWasmInstance(object)); | |
|
ahaas
2016/11/10 09:51:13
same here
titzer
2016/11/10 10:33:25
Done.
| |
| 185 return reinterpret_cast<WasmInstanceObject*>(object); | |
| 186 } | |
| 187 | |
| 188 WasmExportedFunction* WasmExportedFunction::cast(Object* object) { | |
| 189 DCHECK(object->IsJSFunction()); | |
|
ahaas
2016/11/10 09:51:14
same here
titzer
2016/11/10 10:33:25
Done.
| |
| 190 // TODO(titzer): brand check for WasmExportedFunction. | |
| 191 return reinterpret_cast<WasmExportedFunction*>(object); | |
| 192 } | |
| 193 | |
| 194 Handle<WasmCompiledModule> WasmCompiledModule::New( | |
| 195 Isolate* isolate, Handle<WasmModuleWrapper> module_wrapper) { | |
| 196 Handle<FixedArray> ret = | |
| 197 isolate->factory()->NewFixedArray(PropertyIndices::Count, TENURED); | |
| 198 // WasmCompiledModule::cast would fail since module bytes are not set yet. | |
| 199 Handle<WasmCompiledModule> compiled_module( | |
| 200 reinterpret_cast<WasmCompiledModule*>(*ret), isolate); | |
| 201 compiled_module->InitId(); | |
| 202 compiled_module->set_module_wrapper(module_wrapper); | |
| 203 return compiled_module; | |
| 204 } | |
| 205 | |
| 206 wasm::WasmModule* WasmCompiledModule::module() const { | |
| 207 return reinterpret_cast<WasmModuleWrapper*>(*module_wrapper())->get(); | |
| 208 } | |
| 209 | |
| 210 void WasmCompiledModule::InitId() { | |
| 211 #if DEBUG | |
| 212 static uint32_t instance_id_counter = 0; | |
| 213 set(kID_instance_id, Smi::FromInt(instance_id_counter++)); | |
| 214 TRACE("New compiled module id: %d\n", instance_id()); | |
| 215 #endif | |
| 216 } | |
| 217 | |
| 218 bool WasmCompiledModule::IsWasmCompiledModule(Object* obj) { | |
| 219 if (!obj->IsFixedArray()) return false; | |
| 220 FixedArray* arr = FixedArray::cast(obj); | |
| 221 if (arr->length() != PropertyIndices::Count) return false; | |
| 222 Isolate* isolate = arr->GetIsolate(); | |
| 223 #define WCM_CHECK_SMALL_NUMBER(TYPE, NAME) \ | |
| 224 if (!arr->get(kID_##NAME)->IsSmi()) return false; | |
| 225 #define WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME) \ | |
| 226 if (!arr->get(kID_##NAME)->IsUndefined(isolate) && \ | |
| 227 !arr->get(kID_##NAME)->Is##TYPE()) \ | |
| 228 return false; | |
| 229 #define WCM_CHECK_OBJECT(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(TYPE, NAME) | |
| 230 #define WCM_CHECK_WEAK_LINK(TYPE, NAME) WCM_CHECK_OBJECT_OR_WEAK(WeakCell, NAME) | |
| 231 #define WCM_CHECK(KIND, TYPE, NAME) WCM_CHECK_##KIND(TYPE, NAME) | |
| 232 WCM_PROPERTY_TABLE(WCM_CHECK) | |
| 233 #undef WCM_CHECK | |
| 234 | |
| 235 // All checks passed. | |
| 236 return true; | |
| 237 } | |
| 238 | |
| 239 void WasmCompiledModule::PrintInstancesChain() { | |
| 240 #if DEBUG | |
| 241 if (!FLAG_trace_wasm_instances) return; | |
| 242 for (WasmCompiledModule* current = this; current != nullptr;) { | |
| 243 PrintF("->%d", current->instance_id()); | |
| 244 if (current->ptr_to_weak_next_instance() == nullptr) break; | |
| 245 CHECK(!current->ptr_to_weak_next_instance()->cleared()); | |
| 246 current = | |
| 247 WasmCompiledModule::cast(current->ptr_to_weak_next_instance()->value()); | |
| 248 } | |
| 249 PrintF("\n"); | |
| 250 #endif | |
| 251 } | |
| 252 | |
| 253 uint32_t WasmCompiledModule::mem_size() const { | |
| 254 return has_memory() ? memory()->byte_length()->Number() : default_mem_size(); | |
| 255 } | |
| 256 | |
| 257 uint32_t WasmCompiledModule::default_mem_size() const { | |
| 258 return min_mem_pages() * WasmModule::kPageSize; | |
| 259 } | |
| OLD | NEW |