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 |