Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: src/wasm/wasm-js.cc

Issue 2471883003: [wasm] WebAssembly.Memory object can be referenced by multiple Instance objects. (Closed)
Patch Set: Rebase, add Dcheck Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698