| 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 |