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 |