Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(349)

Side by Side Diff: src/wasm/wasm-js.cc

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

Powered by Google App Engine
This is Rietveld 408576698