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 |
| 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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |