Handlify JSFunction::SetPrototype method.

R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/19594002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15738 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 31eeeab3
......@@ -450,26 +450,23 @@ Handle<Object> Accessors::FunctionGetPrototype(Handle<Object> object) {
MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) {
Isolate* isolate = Isolate::Current();
JSFunction* function = FindInstanceOf<JSFunction>(isolate, object);
if (function == NULL) return isolate->heap()->undefined_value();
while (!function->should_have_prototype()) {
function = FindInstanceOf<JSFunction>(isolate, function->GetPrototype());
JSFunction* function_raw = FindInstanceOf<JSFunction>(isolate, object);
if (function_raw == NULL) return isolate->heap()->undefined_value();
while (!function_raw->should_have_prototype()) {
function_raw = FindInstanceOf<JSFunction>(isolate,
function_raw->GetPrototype());
// There has to be one because we hit the getter.
ASSERT(function != NULL);
ASSERT(function_raw != NULL);
}
if (!function->has_prototype()) {
Object* prototype;
{ MaybeObject* maybe_prototype
= isolate->heap()->AllocateFunctionPrototype(function);
if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
}
Object* result;
{ MaybeObject* maybe_result = function->SetPrototype(prototype);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (!function_raw->has_prototype()) {
HandleScope scope(isolate);
Handle<JSFunction> function(function_raw);
Handle<Object> proto = isolate->factory()->NewFunctionPrototype(function);
JSFunction::SetPrototype(function, proto);
function_raw = *function;
}
return function->prototype();
return function_raw->prototype();
}
......@@ -503,9 +500,7 @@ MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
old_value = isolate->factory()->NewFunctionPrototype(function);
}
Handle<Object> result;
MaybeObject* maybe_result = function->SetPrototype(*value);
if (!maybe_result->ToHandle(&result, isolate)) return maybe_result;
JSFunction::SetPrototype(function, value);
ASSERT(function->prototype() == *value);
if (is_observed && !old_value->SameValue(*value)) {
......
......@@ -77,8 +77,6 @@ class Accessors : public AllStatic {
};
// Accessor functions called directly from the runtime system.
MUST_USE_RESULT static MaybeObject* FunctionGetPrototype(Object* object,
void*);
static Handle<Object> FunctionGetPrototype(Handle<Object> object);
MUST_USE_RESULT static MaybeObject* FunctionSetPrototype(JSObject* object,
......@@ -95,6 +93,7 @@ class Accessors : public AllStatic {
static MaybeObject* FunctionGetLength(Object* object, void*);
static MaybeObject* FunctionGetName(Object* object, void*);
static MaybeObject* FunctionGetCaller(Object* object, void*);
static MaybeObject* FunctionGetPrototype(Object* object, void*);
MUST_USE_RESULT static MaybeObject* ArraySetLength(JSObject* object,
Object* value, void*);
static MaybeObject* ArrayGetLength(Object* object, void*);
......
......@@ -200,7 +200,7 @@ class Genesis BASE_EMBEDDED {
// detached from the other objects in the snapshot.
void HookUpInnerGlobal(Handle<GlobalObject> inner_global);
// New context initialization. Used for creating a context from scratch.
bool InitializeGlobal(Handle<GlobalObject> inner_global,
void InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<JSFunction> empty_function);
void InitializeExperimentalGlobal();
// Installs the contents of the native .js files on the global objects.
......@@ -829,7 +829,7 @@ void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
// This is only called if we are not using snapshots. The equivalent
// work in the snapshot case is done in HookUpInnerGlobal.
bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<JSFunction> empty_function) {
// --- G l o b a l C o n t e x t ---
// Use the empty function as closure (no scope info).
......@@ -1053,10 +1053,8 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
Handle<String> name = factory->NewStringFromAscii(CStrVector("JSON"));
Handle<JSFunction> cons = factory->NewFunction(name,
factory->the_hole_value());
{ MaybeObject* result = cons->SetInstancePrototype(
native_context()->initial_object_prototype());
if (result->IsFailure()) return false;
}
JSFunction::SetInstancePrototype(cons,
Handle<Object>(native_context()->initial_object_prototype(), isolate));
cons->SetInstanceClassName(*name);
Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED);
ASSERT(json_object->IsJSObject());
......@@ -1277,7 +1275,6 @@ bool Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
native_context()->set_random_seed(*zeroed_byte_array);
memset(zeroed_byte_array->GetDataStartAddress(), 0, kRandomStateSize);
}
return true;
}
......@@ -2632,7 +2629,7 @@ Genesis::Genesis(Isolate* isolate,
Handle<JSGlobalProxy> global_proxy =
CreateNewGlobals(global_template, global_object, &inner_global);
HookUpGlobalProxy(inner_global, global_proxy);
if (!InitializeGlobal(inner_global, empty_function)) return;
InitializeGlobal(inner_global, empty_function);
InstallJSFunctionResultCaches();
InitializeNormalizedMapCaches();
if (!InstallNatives()) return;
......
......@@ -935,7 +935,7 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
initial_map->set_constructor(*function);
}
SetPrototypeProperty(function, prototype);
JSFunction::SetPrototype(function, prototype);
return function;
}
......
......@@ -169,12 +169,6 @@ void SetExpectedNofProperties(Handle<JSFunction> func, int nof) {
}
void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value) {
CALL_HEAP_FUNCTION_VOID(func->GetIsolate(),
func->SetPrototype(*value));
}
static int ExpectedNofPropertiesFromEstimate(int estimate) {
// If no properties are added in the constructor, they are more likely
// to be added later.
......
......@@ -313,9 +313,6 @@ Handle<String> SubString(Handle<String> str,
// Sets the expected number of properties for the function's instances.
void SetExpectedNofProperties(Handle<JSFunction> func, int nof);
// Sets the prototype property for a function instance.
void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value);
// Sets the expected number of properties based on estimate from compiler.
void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
int estimate);
......
......@@ -9532,57 +9532,53 @@ Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
}
MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
Handle<Object> value) {
ASSERT(value->IsJSReceiver());
Heap* heap = GetHeap();
// First some logic for the map of the prototype to make sure it is in fast
// mode.
if (value->IsJSObject()) {
MaybeObject* ok = JSObject::cast(value)->OptimizeAsPrototype();
if (ok->IsFailure()) return ok;
JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
}
// Now some logic for the maps of the objects that are created by using this
// function as a constructor.
if (has_initial_map()) {
if (function->has_initial_map()) {
// If the function has allocated the initial map replace it with a
// copy containing the new prototype. Also complete any in-object
// slack tracking that is in progress at this point because it is
// still tracking the old copy.
if (shared()->IsInobjectSlackTrackingInProgress()) {
shared()->CompleteInobjectSlackTracking();
if (function->shared()->IsInobjectSlackTrackingInProgress()) {
function->shared()->CompleteInobjectSlackTracking();
}
Map* new_map;
MaybeObject* maybe_object = initial_map()->Copy();
if (!maybe_object->To(&new_map)) return maybe_object;
new_map->set_prototype(value);
Handle<Map> new_map = Map::Copy(handle(function->initial_map()));
new_map->set_prototype(*value);
// If the function is used as the global Array function, cache the
// initial map (and transitioned versions) in the native context.
Context* native_context = context()->native_context();
Context* native_context = function->context()->native_context();
Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
if (array_function->IsJSFunction() &&
this == JSFunction::cast(array_function)) {
MaybeObject* ok = CacheInitialJSArrayMaps(native_context, new_map);
if (ok->IsFailure()) return ok;
*function == JSFunction::cast(array_function)) {
CacheInitialJSArrayMaps(handle(native_context), new_map);
}
set_initial_map(new_map);
function->set_initial_map(*new_map);
} else {
// Put the value in the initial map field until an initial map is
// needed. At that point, a new initial map is created and the
// prototype is put into the initial map where it belongs.
set_prototype_or_initial_map(value);
function->set_prototype_or_initial_map(*value);
}
heap->ClearInstanceofCache();
return value;
function->GetHeap()->ClearInstanceofCache();
}
MaybeObject* JSFunction::SetPrototype(Object* value) {
ASSERT(should_have_prototype());
Object* construct_prototype = value;
void JSFunction::SetPrototype(Handle<JSFunction> function,
Handle<Object> value) {
ASSERT(function->should_have_prototype());
Handle<Object> construct_prototype = value;
// If the value is not a JSReceiver, store the value in the map's
// constructor field so it can be accessed. Also, set the prototype
......@@ -9592,22 +9588,20 @@ MaybeObject* JSFunction::SetPrototype(Object* value) {
// Copy the map so this does not affect unrelated functions.
// Remove map transitions because they point to maps with a
// different prototype.
Map* new_map;
MaybeObject* maybe_new_map = map()->Copy();
if (!maybe_new_map->To(&new_map)) return maybe_new_map;
Handle<Map> new_map = Map::Copy(handle(function->map()));
Heap* heap = new_map->GetHeap();
set_map(new_map);
new_map->set_constructor(value);
function->set_map(*new_map);
new_map->set_constructor(*value);
new_map->set_non_instance_prototype(true);
construct_prototype =
heap->isolate()->context()->native_context()->
initial_object_prototype();
Isolate* isolate = new_map->GetIsolate();
construct_prototype = handle(
isolate->context()->native_context()->initial_object_prototype(),
isolate);
} else {
map()->set_non_instance_prototype(false);
function->map()->set_non_instance_prototype(false);
}
return SetInstancePrototype(construct_prototype);
return SetInstancePrototype(function, construct_prototype);
}
......
......@@ -6695,8 +6695,10 @@ class JSFunction: public JSObject {
inline bool has_instance_prototype();
inline Object* prototype();
inline Object* instance_prototype();
MUST_USE_RESULT MaybeObject* SetInstancePrototype(Object* value);
MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
static void SetPrototype(Handle<JSFunction> function,
Handle<Object> value);
static void SetInstancePrototype(Handle<JSFunction> function,
Handle<Object> value);
// After prototype is removed, it will not be created when accessed, and
// [[Construct]] from this function will not be allowed.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment