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

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

Issue 2350643003: [wasm] Set up Table and Memory constructors (Closed)
Patch Set: 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
« no previous file with comments | « src/wasm/wasm-js.h ('k') | src/wasm/wasm-result.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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
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
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
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
OLDNEW
« no previous file with comments | « src/wasm/wasm-js.h ('k') | src/wasm/wasm-result.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698