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/api-natives.h" | 5 #include "src/api-natives.h" |
6 #include "src/api.h" | 6 #include "src/api.h" |
7 #include "src/asmjs/asm-js.h" | 7 #include "src/asmjs/asm-js.h" |
8 #include "src/asmjs/asm-typer.h" | 8 #include "src/asmjs/asm-typer.h" |
9 #include "src/asmjs/asm-wasm-builder.h" | 9 #include "src/asmjs/asm-wasm-builder.h" |
10 #include "src/assert-scope.h" | 10 #include "src/assert-scope.h" |
(...skipping 11 matching lines...) Expand all Loading... | |
22 #include "src/wasm/wasm-module.h" | 22 #include "src/wasm/wasm-module.h" |
23 #include "src/wasm/wasm-result.h" | 23 #include "src/wasm/wasm-result.h" |
24 | 24 |
25 typedef uint8_t byte; | 25 typedef uint8_t byte; |
26 | 26 |
27 using v8::internal::wasm::ErrorThrower; | 27 using v8::internal::wasm::ErrorThrower; |
28 | 28 |
29 namespace v8 { | 29 namespace v8 { |
30 | 30 |
31 namespace { | 31 namespace { |
32 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { | |
33 return isolate->factory()->NewStringFromAsciiChecked(str); | |
34 } | |
35 Local<String> v8_str(Isolate* isolate, const char* str) { | |
36 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); | |
37 } | |
38 | |
32 struct RawBuffer { | 39 struct RawBuffer { |
33 const byte* start; | 40 const byte* start; |
34 const byte* end; | 41 const byte* end; |
35 size_t size() { return static_cast<size_t>(end - start); } | 42 size_t size() { return static_cast<size_t>(end - start); } |
36 }; | 43 }; |
37 | 44 |
38 RawBuffer GetRawBufferSource( | 45 RawBuffer GetRawBufferSource( |
39 v8::Local<v8::Value> source, ErrorThrower* thrower) { | 46 v8::Local<v8::Value> source, ErrorThrower* thrower) { |
40 const byte* start = nullptr; | 47 const byte* start = nullptr; |
41 const byte* end = nullptr; | 48 const byte* end = nullptr; |
(...skipping 29 matching lines...) Expand all Loading... | |
71 | 78 |
72 return {start, end}; | 79 return {start, end}; |
73 } | 80 } |
74 | 81 |
75 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 82 void VerifyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
76 HandleScope scope(args.GetIsolate()); | 83 HandleScope scope(args.GetIsolate()); |
77 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 84 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
78 ErrorThrower thrower(isolate, "Wasm.verifyModule()"); | 85 ErrorThrower thrower(isolate, "Wasm.verifyModule()"); |
79 | 86 |
80 if (args.Length() < 1) { | 87 if (args.Length() < 1) { |
81 thrower.Error("Argument 0 must be a buffer source"); | 88 thrower.TypeError("Argument 0 must be a buffer source"); |
82 return; | 89 return; |
83 } | 90 } |
84 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | 91 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); |
85 if (thrower.error()) return; | 92 if (thrower.error()) return; |
86 | 93 |
87 i::Zone zone(isolate->allocator()); | 94 i::Zone zone(isolate->allocator()); |
88 internal::wasm::ModuleResult result = | 95 internal::wasm::ModuleResult result = |
89 internal::wasm::DecodeWasmModule(isolate, &zone, buffer.start, buffer.end, | 96 internal::wasm::DecodeWasmModule(isolate, &zone, buffer.start, buffer.end, |
90 true, internal::wasm::kWasmOrigin); | 97 true, internal::wasm::kWasmOrigin); |
91 | 98 |
92 if (result.failed()) { | 99 if (result.failed()) { |
93 thrower.Failed("", result); | 100 thrower.Failed("", result); |
94 } | 101 } |
95 | 102 |
96 if (result.val) delete result.val; | 103 if (result.val) delete result.val; |
97 } | 104 } |
98 | 105 |
99 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { | 106 void VerifyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) { |
100 HandleScope scope(args.GetIsolate()); | 107 HandleScope scope(args.GetIsolate()); |
101 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 108 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
102 ErrorThrower thrower(isolate, "Wasm.verifyFunction()"); | 109 ErrorThrower thrower(isolate, "Wasm.verifyFunction()"); |
103 | 110 |
104 if (args.Length() < 1) { | 111 if (args.Length() < 1) { |
105 thrower.Error("Argument 0 must be a buffer source"); | 112 thrower.TypeError("Argument 0 must be a buffer source"); |
106 return; | 113 return; |
107 } | 114 } |
108 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | 115 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); |
109 if (thrower.error()) return; | 116 if (thrower.error()) return; |
110 | 117 |
111 internal::wasm::FunctionResult result; | 118 internal::wasm::FunctionResult result; |
112 { | 119 { |
113 // Verification of a single function shouldn't allocate. | 120 // Verification of a single function shouldn't allocate. |
114 i::DisallowHeapAllocation no_allocation; | 121 i::DisallowHeapAllocation no_allocation; |
115 i::Zone zone(isolate->allocator()); | 122 i::Zone zone(isolate->allocator()); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
160 } | 167 } |
161 return object; | 168 return object; |
162 } | 169 } |
163 | 170 |
164 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 171 void InstantiateModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
165 HandleScope scope(args.GetIsolate()); | 172 HandleScope scope(args.GetIsolate()); |
166 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); | 173 i::Isolate* isolate = reinterpret_cast<i::Isolate*>(args.GetIsolate()); |
167 ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); | 174 ErrorThrower thrower(isolate, "Wasm.instantiateModule()"); |
168 | 175 |
169 if (args.Length() < 1) { | 176 if (args.Length() < 1) { |
170 thrower.Error("Argument 0 must be a buffer source"); | 177 thrower.TypeError("Argument 0 must be a buffer source"); |
171 return; | 178 return; |
172 } | 179 } |
173 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); | 180 RawBuffer buffer = GetRawBufferSource(args[0], &thrower); |
174 if (buffer.start == nullptr) return; | 181 if (buffer.start == nullptr) return; |
175 | 182 |
176 InstantiateModule(args, buffer.start, buffer.end, &thrower); | 183 InstantiateModule(args, buffer.start, buffer.end, &thrower); |
177 } | 184 } |
178 | 185 |
179 static i::MaybeHandle<i::JSObject> CreateModuleObject( | 186 static i::MaybeHandle<i::JSObject> CreateModuleObject( |
180 v8::Isolate* isolate, const v8::Local<v8::Value> source, | 187 v8::Isolate* isolate, const v8::Local<v8::Value> source, |
181 ErrorThrower* thrower) { | 188 ErrorThrower* thrower) { |
182 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 189 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
183 i::MaybeHandle<i::JSObject> nothing; | 190 i::MaybeHandle<i::JSObject> nothing; |
184 | 191 |
185 RawBuffer buffer = GetRawBufferSource(source, thrower); | 192 RawBuffer buffer = GetRawBufferSource(source, thrower); |
186 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); | 193 if (buffer.start == nullptr) return i::MaybeHandle<i::JSObject>(); |
187 | 194 |
188 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); | 195 DCHECK(source->IsArrayBuffer() || source->IsTypedArray()); |
189 return i::wasm::CreateModuleObjectFromBytes( | 196 return i::wasm::CreateModuleObjectFromBytes( |
190 i_isolate, buffer.start, buffer.end, thrower, | 197 i_isolate, buffer.start, buffer.end, thrower, |
191 i::wasm::ModuleOrigin::kWasmOrigin); | 198 i::wasm::ModuleOrigin::kWasmOrigin); |
192 } | 199 } |
193 | 200 |
201 bool BrandCheck(Isolate* isolate, i::Handle<i::Object> value, | |
202 i::Handle<i::Symbol> sym, const char* msg) { | |
203 if (value->IsJSObject()) { | |
204 i::Handle<i::JSObject> object = i::Handle<i::JSObject>::cast(value); | |
205 Maybe<bool> has_brand = i::JSObject::HasOwnProperty(object, sym); | |
206 if (has_brand.IsNothing()) return false; | |
207 if (has_brand.ToChecked()) return true; | |
208 } | |
209 v8::Local<v8::Value> e = v8::Exception::TypeError(v8_str(isolate, msg)); | |
210 isolate->ThrowException(e); | |
211 return false; | |
212 } | |
213 | |
194 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { | 214 void WebAssemblyCompile(const v8::FunctionCallbackInfo<v8::Value>& args) { |
195 v8::Isolate* isolate = args.GetIsolate(); | 215 v8::Isolate* isolate = args.GetIsolate(); |
196 HandleScope scope(isolate); | 216 HandleScope scope(isolate); |
197 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 217 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
198 "WebAssembly.compile()"); | 218 "WebAssembly.compile()"); |
199 | 219 |
200 if (args.Length() < 1) { | 220 if (args.Length() < 1) { |
201 thrower.Error("Argument 0 must be a buffer source"); | 221 thrower.TypeError("Argument 0 must be a buffer source"); |
202 return; | 222 return; |
203 } | 223 } |
204 i::MaybeHandle<i::JSObject> module_obj = | 224 i::MaybeHandle<i::JSObject> module_obj = |
205 CreateModuleObject(isolate, args[0], &thrower); | 225 CreateModuleObject(isolate, args[0], &thrower); |
206 | 226 |
207 Local<Context> context = isolate->GetCurrentContext(); | 227 Local<Context> context = isolate->GetCurrentContext(); |
208 v8::Local<v8::Promise::Resolver> resolver; | 228 v8::Local<v8::Promise::Resolver> resolver; |
209 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; | 229 if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) return; |
210 if (thrower.error()) { | 230 if (thrower.error()) { |
211 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); | 231 resolver->Reject(context, Utils::ToLocal(thrower.Reify())); |
212 } else { | 232 } else { |
213 resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked())); | 233 resolver->Resolve(context, Utils::ToLocal(module_obj.ToHandleChecked())); |
214 } | 234 } |
215 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 235 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
216 return_value.Set(resolver->GetPromise()); | 236 return_value.Set(resolver->GetPromise()); |
217 } | 237 } |
218 | 238 |
219 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { | 239 void WebAssemblyModule(const v8::FunctionCallbackInfo<v8::Value>& args) { |
220 v8::Isolate* isolate = args.GetIsolate(); | 240 v8::Isolate* isolate = args.GetIsolate(); |
221 HandleScope scope(isolate); | 241 HandleScope scope(isolate); |
222 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | 242 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), |
223 "WebAssembly.Module()"); | 243 "WebAssembly.Module()"); |
224 | 244 |
225 if (args.Length() < 1) { | 245 if (args.Length() < 1) { |
226 thrower.Error("Argument 0 must be a buffer source"); | 246 thrower.TypeError("Argument 0 must be a buffer source"); |
227 return; | 247 return; |
228 } | 248 } |
229 i::MaybeHandle<i::JSObject> module_obj = | 249 i::MaybeHandle<i::JSObject> module_obj = |
230 CreateModuleObject(isolate, args[0], &thrower); | 250 CreateModuleObject(isolate, args[0], &thrower); |
231 if (module_obj.is_null()) return; | 251 if (module_obj.is_null()) return; |
232 | 252 |
233 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 253 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
234 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); | 254 return_value.Set(Utils::ToLocal(module_obj.ToHandleChecked())); |
235 } | 255 } |
236 | 256 |
237 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { | 257 void WebAssemblyInstance(const v8::FunctionCallbackInfo<v8::Value>& args) { |
238 HandleScope scope(args.GetIsolate()); | 258 HandleScope scope(args.GetIsolate()); |
239 v8::Isolate* isolate = args.GetIsolate(); | 259 v8::Isolate* isolate = args.GetIsolate(); |
240 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 260 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
241 | 261 |
242 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); | 262 ErrorThrower thrower(i_isolate, "WebAssembly.Instance()"); |
243 | 263 |
244 if (args.Length() < 1) { | 264 if (args.Length() < 1) { |
245 thrower.Error( | 265 thrower.TypeError("Argument 0 must be a WebAssembly.Module"); |
246 "Argument 0 must be provided, and must be a WebAssembly.Module object"); | |
247 return; | 266 return; |
248 } | 267 } |
249 | 268 |
250 Local<Context> context = isolate->GetCurrentContext(); | 269 Local<Context> context = isolate->GetCurrentContext(); |
251 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 270 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
252 i::Handle<i::Symbol> module_sym(i_context->wasm_module_sym()); | 271 if (!BrandCheck(isolate, Utils::OpenHandle(*args[0]), |
253 i::MaybeHandle<i::Object> source = | 272 i::Handle<i::Symbol>(i_context->wasm_module_sym()), |
254 i::Object::GetProperty(Utils::OpenHandle(*args[0]), module_sym); | 273 "Argument 0 must be a WebAssembly.Module")) { |
255 if (source.is_null() || source.ToHandleChecked()->IsUndefined(i_isolate)) { | |
256 thrower.Error("Argument 0 must be a WebAssembly.Module"); | |
257 return; | 274 return; |
258 } | 275 } |
259 | 276 |
260 Local<Object> obj = Local<Object>::Cast(args[0]); | 277 Local<Object> obj = Local<Object>::Cast(args[0]); |
261 | 278 |
262 i::Handle<i::JSObject> module_obj = | 279 i::Handle<i::JSObject> module_obj = |
263 i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); | 280 i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); |
264 if (module_obj->GetInternalFieldCount() < 1 || | 281 if (module_obj->GetInternalFieldCount() < 1 || |
265 !module_obj->GetInternalField(0)->IsFixedArray()) { | 282 !module_obj->GetInternalField(0)->IsFixedArray()) { |
266 thrower.Error("Argument 0 is an invalid WebAssembly.Module"); | 283 thrower.TypeError("Argument 0 is an invalid WebAssembly.Module"); |
267 return; | 284 return; |
268 } | 285 } |
269 | 286 |
270 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); | 287 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); |
271 if (args.Length() > 1 && args[1]->IsObject()) { | 288 if (args.Length() > 1 && args[1]->IsObject()) { |
272 Local<Object> obj = Local<Object>::Cast(args[1]); | 289 Local<Object> obj = Local<Object>::Cast(args[1]); |
273 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); | 290 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); |
274 } | 291 } |
275 | 292 |
276 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | 293 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); |
277 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { | 294 if (args.Length() > 2 && args[2]->IsArrayBuffer()) { |
278 Local<Object> obj = Local<Object>::Cast(args[2]); | 295 Local<Object> obj = Local<Object>::Cast(args[2]); |
279 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | 296 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); |
280 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); | 297 memory = i::Handle<i::JSArrayBuffer>(i::JSArrayBuffer::cast(*mem_obj)); |
281 } | 298 } |
282 i::MaybeHandle<i::JSObject> instance = | 299 i::MaybeHandle<i::JSObject> instance = |
283 i::wasm::WasmModule::Instantiate(i_isolate, module_obj, ffi, memory); | 300 i::wasm::WasmModule::Instantiate(i_isolate, module_obj, ffi, memory); |
284 if (instance.is_null()) { | 301 if (instance.is_null()) { |
285 thrower.Error("Could not instantiate module"); | 302 thrower.Error("Could not instantiate module"); |
286 return; | 303 return; |
287 } | 304 } |
288 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 305 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
289 return_value.Set(Utils::ToLocal(instance.ToHandleChecked())); | 306 return_value.Set(Utils::ToLocal(instance.ToHandleChecked())); |
290 } | 307 } |
308 | |
309 void WebAssemblyTable(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
310 v8::Isolate* isolate = args.GetIsolate(); | |
311 HandleScope scope(isolate); | |
312 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
313 "WebAssembly.Module()"); | |
314 if (args.Length() < 1 || !args[0]->IsObject()) { | |
315 thrower.TypeError("Argument 0 must be a table descriptor"); | |
316 return; | |
317 } | |
318 Local<Context> context = isolate->GetCurrentContext(); | |
319 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | |
320 // The descriptor's 'element'. | |
321 { | |
322 v8::MaybeLocal<v8::Value> maybe = | |
323 descriptor->Get(context, v8_str(isolate, "element")); | |
324 v8::Local<v8::Value> value; | |
325 if (!maybe.ToLocal(&value)) return; | |
326 v8::Local<v8::String> string; | |
327 if (!value->ToString(context).ToLocal(&string)) return; | |
328 bool equal; | |
329 if (!string->Equals(context, v8_str(isolate, "anyfunc")).To(&equal)) return; | |
330 if (!equal) { | |
331 thrower.TypeError("Descriptor property 'element' must be 'anyfunc'"); | |
332 return; | |
333 } | |
334 } | |
335 // The descriptor's 'initial'. | |
336 int initial; | |
337 { | |
338 v8::MaybeLocal<v8::Value> maybe = | |
339 descriptor->Get(context, v8_str(isolate, "initial")); | |
340 v8::Local<v8::Value> value; | |
341 if (!maybe.ToLocal(&value)) return; | |
342 int64_t number; | |
titzer
2016/09/20 12:37:21
Can we factor out a helper routine for setting a n
ahaas
2016/09/21 09:38:11
Done.
| |
343 if (!value->IntegerValue(context).To(&number)) return; | |
344 if (number < 0) { | |
345 thrower.RangeError("Descriptor property 'initial' must not be negative"); | |
346 return; | |
347 } | |
348 initial = static_cast<int>(number); | |
349 if (initial != number) { | |
350 thrower.RangeError("Descriptor property 'initial' too large"); | |
351 return; | |
352 } | |
353 } | |
354 // The descriptor's 'maximum'. | |
355 Maybe<int> maximum = Nothing<int>(); | |
356 { | |
357 v8::MaybeLocal<v8::Value> maybe = | |
358 descriptor->Get(context, v8_str(isolate, "maximum")); | |
359 v8::Local<v8::Value> value; | |
360 if (maybe.ToLocal(&value) && !value->IsUndefined()) { | |
361 int64_t number; | |
362 if (!value->IntegerValue(context).To(&number)) return; | |
363 if (number < 0) { | |
364 thrower.RangeError( | |
365 "Descriptor property 'maximum' must not be negative"); | |
366 return; | |
367 } | |
368 int num = static_cast<int>(number); | |
369 if (num != number) { | |
370 thrower.RangeError("Descriptor property 'maximum' too large"); | |
371 return; | |
372 } | |
373 if (num < initial) { | |
374 thrower.RangeError( | |
375 "Descriptor property 'maximum' must not be smaller than 'initial'"); | |
376 return; | |
377 } | |
378 maximum = Just(num); | |
379 } | |
380 } | |
381 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
382 i::Handle<i::JSFunction> table_cons( | |
383 i_isolate->native_context()->wasm_table_constructor()); | |
384 i::Handle<i::JSObject> table_obj = | |
385 i_isolate->factory()->NewJSObject(table_cons); | |
386 i::Handle<i::FixedArray> fixed_array = | |
387 i_isolate->factory()->NewFixedArray(initial); | |
388 i::Object* null = i_isolate->heap()->null_value(); | |
389 for (int i = 0; i < initial; ++i) fixed_array->set(i, null); | |
390 table_obj->SetInternalField(0, *fixed_array); | |
391 table_obj->SetInternalField( | |
392 1, maximum.IsNothing() | |
393 ? static_cast<i::Object*>(i_isolate->heap()->undefined_value()) | |
394 : static_cast<i::Object*>(i::Smi::FromInt(maximum.ToChecked()))); | |
395 i::Handle<i::Symbol> table_sym(i_isolate->native_context()->wasm_table_sym()); | |
396 i::Object::SetProperty(table_obj, table_sym, table_obj, i::STRICT).Check(); | |
397 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | |
398 return_value.Set(Utils::ToLocal(table_obj)); | |
399 } | |
400 void WebAssemblyMemory(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
401 v8::Isolate* isolate = args.GetIsolate(); | |
402 HandleScope scope(isolate); | |
403 ErrorThrower thrower(reinterpret_cast<i::Isolate*>(isolate), | |
404 "WebAssembly.Module()"); | |
405 if (args.Length() < 1 || !args[0]->IsObject()) { | |
406 thrower.TypeError("Argument 0 must be a table descriptor"); | |
407 return; | |
408 } | |
409 Local<Context> context = isolate->GetCurrentContext(); | |
410 Local<v8::Object> descriptor = args[0]->ToObject(context).ToLocalChecked(); | |
411 // The descriptor's 'initial'. | |
412 int initial; | |
413 { | |
414 v8::MaybeLocal<v8::Value> maybe = | |
415 descriptor->Get(context, v8_str(isolate, "initial")); | |
416 v8::Local<v8::Value> value; | |
417 if (!maybe.ToLocal(&value)) return; | |
418 int64_t number; | |
419 if (!value->IntegerValue(context).To(&number)) return; | |
420 if (number < 0) { | |
421 thrower.RangeError("Descriptor property 'inital' must not be negative"); | |
422 return; | |
423 } | |
424 initial = static_cast<int>(number); | |
425 if (initial != number || initial > 65536) { | |
426 thrower.RangeError( | |
427 "Descriptor property 'initial' " | |
428 "must not be larger than 65536 (4GiB)"); | |
429 return; | |
430 } | |
431 } | |
432 // The descriptor's 'maximum'. | |
433 Maybe<int> maximum = Nothing<int>(); | |
434 { | |
435 v8::MaybeLocal<v8::Value> maybe = | |
436 descriptor->Get(context, v8_str(isolate, "maximum")); | |
437 v8::Local<v8::Value> value; | |
438 if (maybe.ToLocal(&value) && !value->IsUndefined()) { | |
439 int64_t number; | |
440 if (!value->IntegerValue(context).To(&number)) return; | |
441 if (number < 0) { | |
442 thrower.RangeError( | |
443 "Descriptor property 'maximum' must not be negative"); | |
444 return; | |
445 } | |
446 int num = static_cast<int>(number); | |
447 if (num != number || initial > 65536) { | |
448 thrower.RangeError( | |
449 "Descriptor property 'maximum' must not be larger than 65536 " | |
450 "(4GiB)"); | |
451 return; | |
452 } | |
453 if (num < initial) { | |
454 thrower.RangeError( | |
455 "Descriptor property 'maximum' must not be smaller than 'initial'"); | |
456 return; | |
457 } | |
458 maximum = Just(num); | |
459 } | |
460 } | |
461 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
462 i::Handle<i::JSFunction> memory_cons( | |
463 i_isolate->native_context()->wasm_memory_constructor()); | |
464 i::Handle<i::JSObject> memory_obj = | |
465 i_isolate->factory()->NewJSObject(memory_cons); | |
466 i::Handle<i::JSArrayBuffer> buffer = | |
467 i_isolate->factory()->NewJSArrayBuffer(i::SharedFlag::kNotShared); | |
468 size_t size = static_cast<size_t>(i::wasm::WasmModule::kPageSize) * | |
469 static_cast<size_t>(initial); | |
470 i::JSArrayBuffer::SetupAllocatingData(buffer, i_isolate, size); | |
471 memory_obj->SetInternalField(0, *buffer); | |
472 memory_obj->SetInternalField( | |
473 1, maximum.IsNothing() | |
474 ? static_cast<i::Object*>(i_isolate->heap()->undefined_value()) | |
475 : static_cast<i::Object*>(i::Smi::FromInt(maximum.ToChecked()))); | |
476 i::Handle<i::Symbol> memory_sym( | |
477 i_isolate->native_context()->wasm_memory_sym()); | |
478 i::Object::SetProperty(memory_obj, memory_sym, memory_obj, i::STRICT).Check(); | |
479 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | |
480 return_value.Set(Utils::ToLocal(memory_obj)); | |
481 } | |
482 void WebAssemblyTableGetLength( | |
483 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
484 // TODO(rossberg) | |
485 } | |
486 void WebAssemblyTableGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
487 // TODO(rossberg) | |
488 } | |
489 void WebAssemblyTableGet(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
490 // TODO(rossberg) | |
491 } | |
492 void WebAssemblyTableSet(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
493 // TODO(rossberg) | |
494 } | |
495 void WebAssemblyMemoryGrow(const v8::FunctionCallbackInfo<v8::Value>& args) { | |
496 // TODO(rossberg) | |
497 } | |
498 void WebAssemblyMemoryGetBuffer( | |
499 const v8::FunctionCallbackInfo<v8::Value>& args) { | |
500 v8::Isolate* isolate = args.GetIsolate(); | |
501 Local<Context> context = isolate->GetCurrentContext(); | |
502 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | |
503 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | |
504 i::Handle<i::Symbol>(i_context->wasm_memory_sym()), | |
505 "Receiver is not a WebAssembly.Memory")) { | |
506 return; | |
507 } | |
508 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | |
509 i::Handle<i::JSObject> receiver = | |
510 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); | |
511 i::Handle<i::Object> buffer(receiver->GetInternalField(0), i_isolate); | |
512 DCHECK(buffer->IsJSArrayBuffer()); | |
513 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | |
514 return_value.Set(Utils::ToLocal(buffer)); | |
515 } | |
291 } // namespace | 516 } // namespace |
292 | 517 |
293 // TODO(titzer): we use the API to create the function template because the | 518 // TODO(titzer): we use the API to create the function template because the |
294 // internal guts are too ugly to replicate here. | 519 // internal guts are too ugly to replicate here. |
295 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, | 520 static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate, |
296 FunctionCallback func) { | 521 FunctionCallback func) { |
297 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); | 522 Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate); |
298 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); | 523 Local<FunctionTemplate> local = FunctionTemplate::New(isolate, func); |
299 return v8::Utils::OpenHandle(*local); | 524 return v8::Utils::OpenHandle(*local); |
300 } | 525 } |
301 | 526 |
302 namespace internal { | 527 namespace internal { |
303 static Handle<String> v8_str(Isolate* isolate, const char* str) { | |
304 return isolate->factory()->NewStringFromAsciiChecked(str); | |
305 } | |
306 | 528 |
307 static Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object, | 529 Handle<JSFunction> InstallFunc(Isolate* isolate, Handle<JSObject> object, |
308 const char* str, FunctionCallback func) { | 530 const char* str, FunctionCallback func) { |
309 Handle<String> name = v8_str(isolate, str); | 531 Handle<String> name = v8_str(isolate, str); |
310 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); | 532 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); |
311 Handle<JSFunction> function = | 533 Handle<JSFunction> function = |
312 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); | 534 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); |
313 PropertyAttributes attributes = | 535 PropertyAttributes attributes = |
314 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 536 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
315 JSObject::AddProperty(object, name, function, attributes); | 537 JSObject::AddProperty(object, name, function, attributes); |
316 return function; | 538 return function; |
317 } | 539 } |
318 | 540 |
541 Handle<JSFunction> InstallGetter(Isolate* isolate, Handle<JSObject> object, | |
542 const char* str, FunctionCallback func) { | |
543 Handle<String> name = v8_str(isolate, str); | |
544 Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func); | |
545 Handle<JSFunction> function = | |
546 ApiNatives::InstantiateFunction(temp).ToHandleChecked(); | |
547 v8::PropertyAttribute attributes = | |
548 static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly); | |
549 Utils::ToLocal(object)->SetAccessorProperty(Utils::ToLocal(name), | |
550 Utils::ToLocal(function), | |
551 Local<Function>(), attributes); | |
552 return function; | |
553 } | |
554 | |
319 void WasmJs::InstallWasmModuleSymbolIfNeeded(Isolate* isolate, | 555 void WasmJs::InstallWasmModuleSymbolIfNeeded(Isolate* isolate, |
320 Handle<JSGlobalObject> global, | 556 Handle<JSGlobalObject> global, |
321 Handle<Context> context) { | 557 Handle<Context> context) { |
322 if (!context->get(Context::WASM_MODULE_SYM_INDEX)->IsSymbol() || | 558 if (!context->get(Context::WASM_MODULE_SYM_INDEX)->IsSymbol() || |
323 !context->get(Context::WASM_INSTANCE_SYM_INDEX)->IsSymbol()) { | 559 !context->get(Context::WASM_INSTANCE_SYM_INDEX)->IsSymbol()) { |
324 Factory* factory = isolate->factory(); | 560 InstallWasmMapsIfNeeded(isolate, isolate->native_context()); |
325 // Create private symbols. | 561 InstallWasmConstructors(isolate, isolate->global_object(), |
326 Handle<Symbol> module_sym = factory->NewPrivateSymbol(); | 562 isolate->native_context()); |
327 Handle<Symbol> instance_sym = factory->NewPrivateSymbol(); | 563 } |
328 context->set_wasm_module_sym(*module_sym); | 564 } |
329 context->set_wasm_instance_sym(*instance_sym); | |
330 | 565 |
331 // Bind the WebAssembly object. | 566 void WasmJs::InstallWasmConstructors(Isolate* isolate, |
332 Handle<String> name = v8_str(isolate, "WebAssembly"); | 567 Handle<JSGlobalObject> global, |
333 Handle<JSFunction> cons = factory->NewFunction(name); | 568 Handle<Context> context) { |
334 JSFunction::SetInstancePrototype( | 569 Factory* factory = isolate->factory(); |
335 cons, Handle<Object>(context->initial_object_prototype(), isolate)); | 570 // Create private symbols. |
336 cons->shared()->set_instance_class_name(*name); | 571 Handle<Symbol> module_sym = factory->NewPrivateSymbol(); |
337 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); | 572 Handle<Symbol> instance_sym = factory->NewPrivateSymbol(); |
338 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); | 573 Handle<Symbol> table_sym = factory->NewPrivateSymbol(); |
339 JSObject::AddProperty(global, name, wasm_object, attributes); | 574 Handle<Symbol> memory_sym = factory->NewPrivateSymbol(); |
340 | 575 context->set_wasm_module_sym(*module_sym); |
341 // Install static methods on WebAssembly object. | 576 context->set_wasm_instance_sym(*instance_sym); |
342 InstallFunc(isolate, wasm_object, "compile", WebAssemblyCompile); | 577 context->set_wasm_table_sym(*table_sym); |
343 Handle<JSFunction> module_constructor = | 578 context->set_wasm_memory_sym(*memory_sym); |
344 InstallFunc(isolate, wasm_object, "Module", WebAssemblyModule); | 579 // Bind the WebAssembly object. |
345 Handle<JSFunction> instance_constructor = | 580 Handle<String> name = v8_str(isolate, "WebAssembly"); |
346 InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance); | 581 Handle<JSFunction> cons = factory->NewFunction(name); |
347 i::Handle<i::Map> map = isolate->factory()->NewMap( | 582 JSFunction::SetInstancePrototype( |
348 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + i::kPointerSize); | 583 cons, Handle<Object>(context->initial_object_prototype(), isolate)); |
349 module_constructor->set_prototype_or_initial_map(*map); | 584 cons->shared()->set_instance_class_name(*name); |
350 map->SetConstructor(*module_constructor); | 585 Handle<JSObject> wasm_object = factory->NewJSObject(cons, TENURED); |
351 | 586 PropertyAttributes attributes = static_cast<PropertyAttributes>(DONT_ENUM); |
352 context->set_wasm_module_constructor(*module_constructor); | 587 JSObject::AddProperty(global, name, wasm_object, attributes); |
353 context->set_wasm_instance_constructor(*instance_constructor); | 588 // Install static methods on WebAssembly object. |
354 } | 589 InstallFunc(isolate, wasm_object, "compile", WebAssemblyCompile); |
590 Handle<JSFunction> module_constructor = | |
titzer
2016/09/20 12:37:21
It's tough to see what's going in here exactly, bu
ahaas
2016/09/21 09:38:11
I restructured code now, but I don't think that it
titzer
2016/09/21 09:47:44
Ok, we can always take another crack at it later.
| |
591 InstallFunc(isolate, wasm_object, "Module", WebAssemblyModule); | |
592 Handle<JSFunction> instance_constructor = | |
593 InstallFunc(isolate, wasm_object, "Instance", WebAssemblyInstance); | |
594 Handle<JSFunction> table_constructor = | |
595 InstallFunc(isolate, wasm_object, "Table", WebAssemblyTable); | |
596 Handle<JSFunction> memory_constructor = | |
597 InstallFunc(isolate, wasm_object, "Memory", WebAssemblyMemory); | |
598 context->set_wasm_module_constructor(*module_constructor); | |
599 context->set_wasm_instance_constructor(*instance_constructor); | |
600 context->set_wasm_table_constructor(*table_constructor); | |
601 context->set_wasm_memory_constructor(*memory_constructor); | |
602 // Set up prototypes and instance maps. | |
603 Handle<JSObject> module_proto = | |
604 factory->NewJSObject(module_constructor, TENURED); | |
605 i::Handle<i::Map> map = isolate->factory()->NewMap( | |
606 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + i::kPointerSize); | |
607 JSFunction::SetInitialMap(module_constructor, map, module_proto); | |
608 Handle<JSObject> table_proto = | |
609 factory->NewJSObject(table_constructor, TENURED); | |
610 map = isolate->factory()->NewMap( | |
611 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + 2 * i::kPointerSize); | |
612 JSFunction::SetInitialMap(table_constructor, map, table_proto); | |
613 Handle<JSObject> memory_proto = | |
614 factory->NewJSObject(memory_constructor, TENURED); | |
615 map = isolate->factory()->NewMap( | |
616 i::JS_OBJECT_TYPE, i::JSObject::kHeaderSize + 2 * i::kPointerSize); | |
617 JSFunction::SetInitialMap(memory_constructor, map, memory_proto); | |
618 // Add prototype properties. | |
619 JSObject::AddProperty(module_proto, isolate->factory()->constructor_string(), | |
620 module_constructor, DONT_ENUM); | |
621 JSObject::AddProperty(table_proto, isolate->factory()->constructor_string(), | |
622 table_constructor, DONT_ENUM); | |
623 InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength); | |
624 InstallFunc(isolate, table_proto, "grow", WebAssemblyTableGrow); | |
625 InstallFunc(isolate, table_proto, "get", WebAssemblyTableGet); | |
626 InstallFunc(isolate, table_proto, "set", WebAssemblyTableSet); | |
627 JSObject::AddProperty(memory_proto, isolate->factory()->constructor_string(), | |
628 memory_constructor, DONT_ENUM); | |
629 InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow); | |
630 InstallGetter(isolate, memory_proto, "buffer", WebAssemblyMemoryGetBuffer); | |
355 } | 631 } |
356 | 632 |
357 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { | 633 void WasmJs::Install(Isolate* isolate, Handle<JSGlobalObject> global) { |
358 if (!FLAG_expose_wasm && !FLAG_validate_asm) { | 634 if (!FLAG_expose_wasm && !FLAG_validate_asm) { |
359 return; | 635 return; |
360 } | 636 } |
361 | 637 |
362 Factory* factory = isolate->factory(); | 638 Factory* factory = isolate->factory(); |
363 | 639 |
364 // Setup wasm function map. | 640 // Setup wasm function map. |
365 Handle<Context> context(global->native_context(), isolate); | 641 Handle<Context> context(global->native_context(), isolate); |
366 InstallWasmFunctionMapIfNeeded(isolate, context); | 642 InstallWasmMapsIfNeeded(isolate, context); |
367 | 643 |
368 if (!FLAG_expose_wasm) { | 644 if (!FLAG_expose_wasm) { |
369 return; | 645 return; |
370 } | 646 } |
371 | 647 |
372 // Bind the experimental WASM object. | 648 // Bind the experimental WASM object. |
373 // TODO(rossberg, titzer): remove once it's no longer needed. | 649 // TODO(rossberg, titzer): remove once it's no longer needed. |
374 { | 650 { |
375 Handle<String> name = v8_str(isolate, "Wasm"); | 651 Handle<String> name = v8_str(isolate, "Wasm"); |
376 Handle<JSFunction> cons = factory->NewFunction(name); | 652 Handle<JSFunction> cons = factory->NewFunction(name); |
(...skipping 12 matching lines...) Expand all Loading... | |
389 { | 665 { |
390 // Add the Wasm.experimentalVersion property. | 666 // Add the Wasm.experimentalVersion property. |
391 Handle<String> name = v8_str(isolate, "experimentalVersion"); | 667 Handle<String> name = v8_str(isolate, "experimentalVersion"); |
392 PropertyAttributes attributes = | 668 PropertyAttributes attributes = |
393 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); | 669 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); |
394 Handle<Smi> value = | 670 Handle<Smi> value = |
395 Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate); | 671 Handle<Smi>(Smi::FromInt(wasm::kWasmVersion), isolate); |
396 JSObject::AddProperty(wasm_object, name, value, attributes); | 672 JSObject::AddProperty(wasm_object, name, value, attributes); |
397 } | 673 } |
398 } | 674 } |
399 InstallWasmModuleSymbolIfNeeded(isolate, global, context); | 675 InstallWasmConstructors(isolate, global, context); |
400 } | 676 } |
401 | 677 |
402 void WasmJs::InstallWasmFunctionMapIfNeeded(Isolate* isolate, | 678 void WasmJs::InstallWasmMapsIfNeeded(Isolate* isolate, |
403 Handle<Context> context) { | 679 Handle<Context> context) { |
404 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { | 680 if (!context->get(Context::WASM_FUNCTION_MAP_INDEX)->IsMap()) { |
405 // TODO(titzer): Move this to bootstrapper.cc?? | 681 // TODO(titzer): Move this to bootstrapper.cc?? |
406 // TODO(titzer): Also make one for strict mode functions? | 682 // TODO(titzer): Also make one for strict mode functions? |
407 Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate); | 683 Handle<Map> prev_map = Handle<Map>(context->sloppy_function_map(), isolate); |
408 | 684 |
409 InstanceType instance_type = prev_map->instance_type(); | 685 InstanceType instance_type = prev_map->instance_type(); |
410 int internal_fields = JSObject::GetInternalFieldCount(*prev_map); | 686 int internal_fields = JSObject::GetInternalFieldCount(*prev_map); |
411 CHECK_EQ(0, internal_fields); | 687 CHECK_EQ(0, internal_fields); |
412 int pre_allocated = | 688 int pre_allocated = |
413 prev_map->GetInObjectProperties() - prev_map->unused_property_fields(); | 689 prev_map->GetInObjectProperties() - prev_map->unused_property_fields(); |
414 int instance_size = 0; | 690 int instance_size = 0; |
415 int in_object_properties = 0; | 691 int in_object_properties = 0; |
416 int wasm_internal_fields = internal_fields + 1 // module instance object | 692 int wasm_internal_fields = internal_fields + 1 // module instance object |
417 + 1 // function arity | 693 + 1 // function arity |
418 + 1; // function signature | 694 + 1; // function signature |
419 JSFunction::CalculateInstanceSizeHelper(instance_type, wasm_internal_fields, | 695 JSFunction::CalculateInstanceSizeHelper(instance_type, wasm_internal_fields, |
420 0, &instance_size, | 696 0, &instance_size, |
421 &in_object_properties); | 697 &in_object_properties); |
422 | 698 |
423 int unused_property_fields = in_object_properties - pre_allocated; | 699 int unused_property_fields = in_object_properties - pre_allocated; |
424 Handle<Map> map = Map::CopyInitialMap( | 700 Handle<Map> map = Map::CopyInitialMap( |
425 prev_map, instance_size, in_object_properties, unused_property_fields); | 701 prev_map, instance_size, in_object_properties, unused_property_fields); |
426 | 702 |
427 context->set_wasm_function_map(*map); | 703 context->set_wasm_function_map(*map); |
428 } | 704 } |
429 } | 705 } |
430 | 706 |
431 } // namespace internal | 707 } // namespace internal |
432 } // namespace v8 | 708 } // namespace v8 |
OLD | NEW |