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