Chromium Code Reviews| 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 16 matching lines...) Expand all Loading... | |
| 27 | 27 |
| 28 namespace v8 { | 28 namespace v8 { |
| 29 | 29 |
| 30 static const int kWasmTableArrayFieldIndex = 0; | 30 static const int kWasmTableArrayFieldIndex = 0; |
| 31 static const int kWasmTableMaximumFieldIndex = 1; | 31 static const int kWasmTableMaximumFieldIndex = 1; |
| 32 static const int kWasmTableDispatchTablesFieldIndex = 2; | 32 static const int kWasmTableDispatchTablesFieldIndex = 2; |
| 33 | 33 |
| 34 enum WasmMemoryObjectData { | 34 enum WasmMemoryObjectData { |
| 35 kWasmMemoryBuffer, | 35 kWasmMemoryBuffer, |
| 36 kWasmMemoryMaximum, | 36 kWasmMemoryMaximum, |
| 37 kWasmMemoryInstanceObject | 37 kWasmMemoryInstancesLink, |
|
titzer
2016/11/07 19:34:07
I think this might be a bit simpler if we just use
gdeepti
2016/11/09 01:26:17
Do you mean using a FixedArray to store weak links
bradnelson
2016/11/09 01:40:11
So this is currently keeping a doubly-linked (stro
| |
| 38 kWasmMemoryInternalFieldCount | |
| 38 }; | 39 }; |
| 39 | 40 |
| 40 enum WasmInternalFieldCountData { | 41 enum WasmInternalFieldCountData { kWasmTableInternalFieldCount = 3 }; |
| 41 kWasmTableInternalFieldCount = 3, | |
| 42 kWasmMemoryInternalFieldCount = 3 | |
| 43 }; | |
| 44 | 42 |
| 45 namespace { | 43 namespace { |
| 46 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { | 44 i::Handle<i::String> v8_str(i::Isolate* isolate, const char* str) { |
| 47 return isolate->factory()->NewStringFromAsciiChecked(str); | 45 return isolate->factory()->NewStringFromAsciiChecked(str); |
| 48 } | 46 } |
| 49 Local<String> v8_str(Isolate* isolate, const char* str) { | 47 Local<String> v8_str(Isolate* isolate, const char* str) { |
| 50 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); | 48 return Utils::ToLocal(v8_str(reinterpret_cast<i::Isolate*>(isolate), str)); |
| 51 } | 49 } |
| 52 | 50 |
| 53 struct RawBuffer { | 51 struct RawBuffer { |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 i::Handle<i::JSObject> i_obj = | 220 i::Handle<i::JSObject> i_obj = |
| 223 i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); | 221 i::Handle<i::JSObject>::cast(v8::Utils::OpenHandle(*obj)); |
| 224 | 222 |
| 225 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); | 223 i::Handle<i::JSReceiver> ffi = i::Handle<i::JSObject>::null(); |
| 226 if (args.Length() > 1 && args[1]->IsObject()) { | 224 if (args.Length() > 1 && args[1]->IsObject()) { |
| 227 Local<Object> obj = Local<Object>::Cast(args[1]); | 225 Local<Object> obj = Local<Object>::Cast(args[1]); |
| 228 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); | 226 ffi = i::Handle<i::JSReceiver>::cast(v8::Utils::OpenHandle(*obj)); |
| 229 } | 227 } |
| 230 | 228 |
| 231 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); | 229 i::Handle<i::JSArrayBuffer> memory = i::Handle<i::JSArrayBuffer>::null(); |
| 230 i::Handle<i::Object> mem_obj; | |
| 232 if (args.Length() > 2 && args[2]->IsObject()) { | 231 if (args.Length() > 2 && args[2]->IsObject()) { |
| 233 Local<Object> obj = Local<Object>::Cast(args[2]); | 232 Local<Object> obj = Local<Object>::Cast(args[2]); |
| 234 i::Handle<i::Object> mem_obj = v8::Utils::OpenHandle(*obj); | 233 mem_obj = v8::Utils::OpenHandle(*obj); |
| 235 if (i::WasmJs::IsWasmMemoryObject(i_isolate, mem_obj)) { | 234 if (i::WasmJs::IsWasmMemoryObject(i_isolate, mem_obj)) { |
| 236 memory = i::WasmJs::GetWasmMemoryArrayBuffer(i_isolate, mem_obj); | 235 memory = i::WasmJs::GetWasmMemoryArrayBuffer(i_isolate, mem_obj); |
| 237 } else { | 236 } else { |
| 238 thrower.TypeError("Argument 2 must be a WebAssembly.Memory"); | 237 thrower.TypeError("Argument 2 must be a WebAssembly.Memory"); |
| 238 return; | |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 i::MaybeHandle<i::JSObject> instance = | 241 i::MaybeHandle<i::JSObject> instance = |
| 242 i::wasm::WasmModule::Instantiate(i_isolate, &thrower, i_obj, ffi, memory); | 242 i::wasm::WasmModule::Instantiate(i_isolate, &thrower, i_obj, ffi, memory); |
| 243 if (instance.is_null()) { | 243 if (instance.is_null()) { |
| 244 if (!thrower.error()) thrower.RuntimeError("Could not instantiate module"); | 244 if (!thrower.error()) thrower.RuntimeError("Could not instantiate module"); |
| 245 return; | 245 return; |
| 246 } | 246 } |
| 247 | |
| 248 // TODO(gdeepti): Seems like the right place for this would be in instantiate | |
| 249 // flow, fix to use memory object as an external memory import when passed in | |
| 250 // as an argument. | |
| 251 if (args.Length() > 2 && args[2]->IsObject()) { | |
|
Mircea Trofin
2016/11/09 18:57:09
there's another place we check if args.Length() >
gdeepti
2016/11/16 05:34:09
This is no longer required after refactoring, remo
| |
| 252 i::WasmJs::SetWasmMemoryInstance(i_isolate, mem_obj, | |
| 253 instance.ToHandleChecked()); | |
| 254 internal::wasm::SetInstanceMemoryObject(instance.ToHandleChecked(), | |
| 255 mem_obj); | |
| 256 } | |
| 247 DCHECK(!i_isolate->has_pending_exception()); | 257 DCHECK(!i_isolate->has_pending_exception()); |
| 248 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 258 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 249 return_value.Set(Utils::ToLocal(instance.ToHandleChecked())); | 259 return_value.Set(Utils::ToLocal(instance.ToHandleChecked())); |
| 250 } | 260 } |
| 251 | 261 |
| 252 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, | 262 bool GetIntegerProperty(v8::Isolate* isolate, ErrorThrower* thrower, |
| 253 Local<Context> context, Local<v8::Object> object, | 263 Local<Context> context, Local<v8::Object> object, |
| 254 Local<String> property, int* result, int lower_bound, | 264 Local<String> property, int* result, int lower_bound, |
| 255 int upper_bound) { | 265 int upper_bound) { |
| 256 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); | 266 v8::MaybeLocal<v8::Value> maybe = object->Get(context, property); |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 545 } | 555 } |
| 546 if (args.Length() < 1) { | 556 if (args.Length() < 1) { |
| 547 v8::Local<v8::Value> e = v8::Exception::TypeError( | 557 v8::Local<v8::Value> e = v8::Exception::TypeError( |
| 548 v8_str(isolate, "Argument 0 required, must be numeric value of pages")); | 558 v8_str(isolate, "Argument 0 required, must be numeric value of pages")); |
| 549 isolate->ThrowException(e); | 559 isolate->ThrowException(e); |
| 550 return; | 560 return; |
| 551 } | 561 } |
| 552 | 562 |
| 553 uint32_t delta = args[0]->Uint32Value(context).FromJust(); | 563 uint32_t delta = args[0]->Uint32Value(context).FromJust(); |
| 554 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); | 564 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| 555 i::Handle<i::JSObject> receiver = | 565 i::Handle<i::Object> receiver = |
| 556 i::Handle<i::JSObject>::cast(Utils::OpenHandle(*args.This())); | 566 i::Handle<i::Object>::cast(Utils::OpenHandle(*args.This())); |
| 557 i::Handle<i::Object> instance_object( | 567 int32_t ret = i::wasm::GrowWebAssemblyMemory(i_isolate, receiver, delta); |
| 558 receiver->GetInternalField(kWasmMemoryInstanceObject), i_isolate); | |
| 559 i::Handle<i::JSObject> instance( | |
| 560 i::Handle<i::JSObject>::cast(instance_object)); | |
| 561 | |
| 562 // TODO(gdeepti) Implement growing memory when shared by different | |
| 563 // instances. | |
| 564 int32_t ret = internal::wasm::GrowInstanceMemory(i_isolate, instance, delta); | |
| 565 if (ret == -1) { | 568 if (ret == -1) { |
| 566 v8::Local<v8::Value> e = v8::Exception::Error( | 569 v8::Local<v8::Value> e = v8::Exception::Error( |
| 567 v8_str(isolate, "Unable to grow instance memory.")); | 570 v8_str(isolate, "Unable to grow instance memory.")); |
| 568 isolate->ThrowException(e); | 571 isolate->ThrowException(e); |
| 569 return; | 572 return; |
| 570 } | 573 } |
| 571 i::MaybeHandle<i::JSArrayBuffer> buffer = | |
| 572 internal::wasm::GetInstanceMemory(i_isolate, instance); | |
| 573 if (buffer.is_null()) { | |
| 574 v8::Local<v8::Value> e = v8::Exception::Error( | |
| 575 v8_str(isolate, "WebAssembly.Memory buffer object not set.")); | |
| 576 isolate->ThrowException(e); | |
| 577 return; | |
| 578 } | |
| 579 receiver->SetInternalField(kWasmMemoryBuffer, *buffer.ToHandleChecked()); | |
| 580 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); | 574 v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); |
| 581 return_value.Set(ret); | 575 return_value.Set(ret); |
| 582 } | 576 } |
| 583 | 577 |
| 584 void WebAssemblyMemoryGetBuffer( | 578 void WebAssemblyMemoryGetBuffer( |
| 585 const v8::FunctionCallbackInfo<v8::Value>& args) { | 579 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 586 v8::Isolate* isolate = args.GetIsolate(); | 580 v8::Isolate* isolate = args.GetIsolate(); |
| 587 Local<Context> context = isolate->GetCurrentContext(); | 581 Local<Context> context = isolate->GetCurrentContext(); |
| 588 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); | 582 i::Handle<i::Context> i_context = Utils::OpenHandle(*context); |
| 589 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), | 583 if (!BrandCheck(isolate, Utils::OpenHandle(*args.This()), |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 913 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kV8MaxPages; | 907 if (max_mem->IsUndefined(isolate)) return wasm::WasmModule::kV8MaxPages; |
| 914 uint32_t max_pages = Smi::cast(max_mem)->value(); | 908 uint32_t max_pages = Smi::cast(max_mem)->value(); |
| 915 return max_pages; | 909 return max_pages; |
| 916 } | 910 } |
| 917 | 911 |
| 918 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, | 912 void WasmJs::SetWasmMemoryInstance(Isolate* isolate, |
| 919 Handle<Object> memory_object, | 913 Handle<Object> memory_object, |
| 920 Handle<JSObject> instance) { | 914 Handle<JSObject> instance) { |
| 921 if (!memory_object->IsUndefined(isolate)) { | 915 if (!memory_object->IsUndefined(isolate)) { |
| 922 DCHECK(IsWasmMemoryObject(isolate, memory_object)); | 916 DCHECK(IsWasmMemoryObject(isolate, memory_object)); |
| 923 // TODO(gdeepti): This should be a weak list of instance objects | 917 Object* instance_link = JSObject::cast(*memory_object) |
| 924 // for instances that share memory. | 918 ->GetInternalField(kWasmMemoryInstancesLink); |
| 919 Handle<wasm::WasmInstanceWrapper> instance_wrapper; | |
| 920 if (instance_link->IsUndefined(isolate)) { | |
| 921 instance_wrapper = wasm::WasmInstanceWrapper::New(isolate, instance); | |
| 922 } else { | |
| 923 Handle<wasm::WasmInstanceWrapper> current_wrapper = | |
| 924 handle(wasm::WasmInstanceWrapper::cast(instance_link)); | |
| 925 DCHECK( | |
| 926 wasm::WasmInstanceWrapper::IsWasmInstanceWrapper(*current_wrapper)); | |
| 927 DCHECK(!current_wrapper->has_previous()); | |
| 928 instance_wrapper = wasm::WasmInstanceWrapper::New(isolate, instance); | |
| 929 instance_wrapper->set_next_wrapper(*current_wrapper); | |
| 930 current_wrapper->set_previous_wrapper(*instance_wrapper); | |
| 931 } | |
| 925 JSObject::cast(*memory_object) | 932 JSObject::cast(*memory_object) |
| 926 ->SetInternalField(kWasmMemoryInstanceObject, *instance); | 933 ->SetInternalField(kWasmMemoryInstancesLink, *instance_wrapper); |
| 934 const int kWasmMemInstanceWrapper = 5; | |
|
Mircea Trofin
2016/11/09 18:57:09
This is fragile, because this value here ("5") nee
gdeepti
2016/11/16 05:34:09
Done.
| |
| 935 instance->SetInternalField(kWasmMemInstanceWrapper, *instance_wrapper); | |
| 927 } | 936 } |
| 928 } | 937 } |
| 938 | |
| 939 void WasmJs::ResetWasmMemoryInstance(Isolate* isolate, | |
| 940 Handle<Object> memory_object) { | |
| 941 Handle<Object> undefined = isolate->factory()->undefined_value(); | |
| 942 JSObject::cast(*memory_object) | |
| 943 ->SetInternalField(kWasmMemoryInstancesLink, *undefined); | |
| 944 } | |
| 945 | |
| 946 Handle<Object> WasmJs::GetWasmMemoryInstanceWrapper(Isolate* isolate, | |
| 947 Handle<Object> value) { | |
| 948 DCHECK(IsWasmMemoryObject(isolate, value)); | |
| 949 Handle<Object> obj( | |
| 950 JSObject::cast(*value)->GetInternalField(kWasmMemoryInstancesLink), | |
| 951 isolate); | |
| 952 return obj; | |
| 953 } | |
| 929 } // namespace internal | 954 } // namespace internal |
| 930 } // namespace v8 | 955 } // namespace v8 |
| OLD | NEW |