Skip to content

Commit

Permalink
Merged: [runtime] Mark old JSGlobalProxy's map as unstable when an if…
Browse files Browse the repository at this point in the history
…rame navigates away.

Revision: 1c7f839

BUG=chromium:683667
LOG=N
NOTRY=true
NOPRESUBMIT=true
NOTREECHECKS=true
R=verwaest@chromium.org

Review-Url: https://codereview.chromium.org/2725153002 .
Cr-Commit-Position: refs/branch-heads/5.8@{crosswalk-project#6}
Cr-Branched-From: eda659c-refs/heads/5.8.283@{crosswalk-project#1}
Cr-Branched-From: 4310cd0-refs/heads/master@{#43429}
  • Loading branch information
isheludko committed Mar 2, 2017
1 parent 624059f commit f81c002
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 22 deletions.
61 changes: 45 additions & 16 deletions src/d8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -857,20 +857,24 @@ void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
}

MaybeLocal<Context> Shell::CreateRealm(
const v8::FunctionCallbackInfo<v8::Value>& args) {
const v8::FunctionCallbackInfo<v8::Value>& args, int index,
v8::MaybeLocal<Value> global_object) {
Isolate* isolate = args.GetIsolate();
TryCatch try_catch(isolate);
PerIsolateData* data = PerIsolateData::Get(isolate);
Global<Context>* old_realms = data->realms_;
int index = data->realm_count_;
data->realms_ = new Global<Context>[++data->realm_count_];
for (int i = 0; i < index; ++i) {
data->realms_[i].Reset(isolate, old_realms[i]);
old_realms[i].Reset();
}
delete[] old_realms;
if (index < 0) {
Global<Context>* old_realms = data->realms_;
index = data->realm_count_;
data->realms_ = new Global<Context>[++data->realm_count_];
for (int i = 0; i < index; ++i) {
data->realms_[i].Reset(isolate, old_realms[i]);
old_realms[i].Reset();
}
delete[] old_realms;
}
Local<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
Local<Context> context = Context::New(isolate, NULL, global_template);
Local<Context> context =
Context::New(isolate, NULL, global_template, global_object);
if (context.IsEmpty()) {
DCHECK(try_catch.HasCaught());
try_catch.ReThrow();
Expand All @@ -882,23 +886,47 @@ MaybeLocal<Context> Shell::CreateRealm(
return context;
}

void Shell::DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
int index) {
Isolate* isolate = args.GetIsolate();
PerIsolateData* data = PerIsolateData::Get(isolate);
DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
data->realms_[index].Reset();
isolate->ContextDisposedNotification();
isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
}

// Realm.create() creates a new realm with a distinct security token
// and returns its index.
void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
CreateRealm(args);
CreateRealm(args, -1, v8::MaybeLocal<Value>());
}

// Realm.createAllowCrossRealmAccess() creates a new realm with the same
// security token as the current realm.
void Shell::RealmCreateAllowCrossRealmAccess(
const v8::FunctionCallbackInfo<v8::Value>& args) {
Local<Context> context;
if (CreateRealm(args).ToLocal(&context)) {
if (CreateRealm(args, -1, v8::MaybeLocal<Value>()).ToLocal(&context)) {
context->SetSecurityToken(
args.GetIsolate()->GetEnteredContext()->GetSecurityToken());
}
}

// Realm.navigate(i) creates a new realm with a distinct security token
// in place of realm i.
void Shell::RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
PerIsolateData* data = PerIsolateData::Get(isolate);
int index = data->RealmIndexOrThrow(args, 0);
if (index == -1) return;

Local<Context> context = Local<Context>::New(isolate, data->realms_[index]);
v8::MaybeLocal<Value> global_object = context->Global();
DisposeRealm(args, index);
CreateRealm(args, index, global_object);
}

// Realm.dispose(i) disposes the reference to the realm i.
void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = args.GetIsolate();
Expand All @@ -910,10 +938,7 @@ void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
Throw(args.GetIsolate(), "Invalid realm index");
return;
}
DisposeModuleEmbedderData(data->realms_[index].Get(isolate));
data->realms_[index].Reset();
isolate->ContextDisposedNotification();
isolate->IdleNotificationDeadline(g_platform->MonotonicallyIncreasingTime());
DisposeRealm(args, index);
}


Expand Down Expand Up @@ -1480,6 +1505,10 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
NewStringType::kNormal)
.ToLocalChecked(),
FunctionTemplate::New(isolate, RealmCreateAllowCrossRealmAccess));
realm_template->Set(
String::NewFromUtf8(isolate, "navigate", NewStringType::kNormal)
.ToLocalChecked(),
FunctionTemplate::New(isolate, RealmNavigate));
realm_template->Set(
String::NewFromUtf8(isolate, "dispose", NewStringType::kNormal)
.ToLocalChecked(),
Expand Down
6 changes: 5 additions & 1 deletion src/d8.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ class Shell : public i::AllStatic {
static void RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmNavigate(const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmCreateAllowCrossRealmAccess(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args);
Expand Down Expand Up @@ -475,7 +476,10 @@ class Shell : public i::AllStatic {
static bool SetOptions(int argc, char* argv[]);
static Local<ObjectTemplate> CreateGlobalTemplate(Isolate* isolate);
static MaybeLocal<Context> CreateRealm(
const v8::FunctionCallbackInfo<v8::Value>& args);
const v8::FunctionCallbackInfo<v8::Value>& args, int index,
v8::MaybeLocal<Value> global_object);
static void DisposeRealm(const v8::FunctionCallbackInfo<v8::Value>& args,
int index);
static MaybeLocal<Module> FetchModuleTree(v8::Local<v8::Context> context,
const std::string& file_name);
};
Expand Down
1 change: 1 addition & 0 deletions src/factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2330,6 +2330,7 @@ void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
map->set_is_prototype_map(true);
}
JSObject::NotifyMapChange(old_map, map, isolate());
old_map->NotifyLeafMapLayoutChange();

// Check that the already allocated object has the same size and type as
// objects allocated using the constructor.
Expand Down
10 changes: 5 additions & 5 deletions src/objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -6268,6 +6268,11 @@ class Map: public HeapObject {
Handle<Map> split_map, Handle<DescriptorArray> descriptors,
Handle<LayoutDescriptor> full_layout_descriptor);

// Fires when the layout of an object with a leaf map changes.
// This includes adding transitions to the leaf map or changing
// the descriptor array.
inline void NotifyLeafMapLayoutChange();

private:
// Returns the map that this (root) map transitions to if its elements_kind
// is changed to |elements_kind|, or |nullptr| if no such map is cached yet.
Expand Down Expand Up @@ -6321,11 +6326,6 @@ class Map: public HeapObject {
Handle<Map> map, ElementsKind elements_kind, int modify_index,
PropertyKind kind, PropertyAttributes attributes, const char* reason);

// Fires when the layout of an object with a leaf map changes.
// This includes adding transitions to the leaf map or changing
// the descriptor array.
inline void NotifyLeafMapLayoutChange();

void DeprecateTransitionTree();

void ReplaceDescriptors(DescriptorArray* new_descriptors,
Expand Down
14 changes: 14 additions & 0 deletions test/mjsunit/regress/regress-crbug-683667.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --expose-gc --verify-heap

var realm = Realm.create();
var g = Realm.global(realm);
var obj = {x: 0, g: g};

// Navigation will replace JSGlobalObject behind the JSGlobalProxy g and
// therefore will change the g's map. The old map must be marked as non-stable.
Realm.navigate(realm);
gc();

0 comments on commit f81c002

Please sign in to comment.