Pass in the map while creating JSFunction, and set prototype in the client.
BUG= R=ishell@chromium.org Review URL: https://codereview.chromium.org/263083008 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21166 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
f2903b6f6c
commit
af2be5b4be
286
src/factory.cc
286
src/factory.cc
@ -906,36 +906,6 @@ Handle<Map> Factory::NewMap(InstanceType type,
|
||||
}
|
||||
|
||||
|
||||
Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
||||
// Make sure to use globals from the function's context, since the function
|
||||
// can be from a different context.
|
||||
Handle<Context> native_context(function->context()->native_context());
|
||||
Handle<Map> new_map;
|
||||
if (function->shared()->is_generator()) {
|
||||
// Generator prototypes can share maps since they don't have "constructor"
|
||||
// properties.
|
||||
new_map = handle(native_context->generator_object_prototype_map());
|
||||
} else {
|
||||
// Each function prototype gets a fresh map to avoid unwanted sharing of
|
||||
// maps between prototypes of different constructors.
|
||||
Handle<JSFunction> object_function(native_context->object_function());
|
||||
ASSERT(object_function->has_initial_map());
|
||||
new_map = Map::Copy(handle(object_function->initial_map()));
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
||||
|
||||
if (!function->shared()->is_generator()) {
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(prototype,
|
||||
constructor_string(),
|
||||
function,
|
||||
DONT_ENUM).Assert();
|
||||
}
|
||||
|
||||
return prototype;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSObject> Factory::CopyJSObject(Handle<JSObject> object) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->CopyJSObject(*object, NULL),
|
||||
@ -994,55 +964,6 @@ Handle<ConstantPoolArray> Factory::CopyConstantPoolArray(
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
PretenureFlag pretenure) {
|
||||
Handle<JSFunction> result = NewFunction(
|
||||
info, context, the_hole_value(), pretenure);
|
||||
|
||||
if (info->ic_age() != isolate()->heap()->global_ic_age()) {
|
||||
info->ResetForNewContext(isolate()->heap()->global_ic_age());
|
||||
}
|
||||
|
||||
int index = info->SearchOptimizedCodeMap(context->native_context(),
|
||||
BailoutId::None());
|
||||
if (!info->bound() && index < 0) {
|
||||
int number_of_literals = info->num_literals();
|
||||
Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
|
||||
if (number_of_literals > 0) {
|
||||
// Store the native context in the literals array prefix. This
|
||||
// context will be used when creating object, regexp and array
|
||||
// literals in this function.
|
||||
literals->set(JSFunction::kLiteralNativeContextIndex,
|
||||
context->native_context());
|
||||
}
|
||||
result->set_literals(*literals);
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
// Caching of optimized code enabled and optimized code found.
|
||||
FixedArray* literals = info->GetLiteralsFromOptimizedCodeMap(index);
|
||||
if (literals != NULL) result->set_literals(literals);
|
||||
Code* code = info->GetCodeFromOptimizedCodeMap(index);
|
||||
ASSERT(!code->marked_for_deoptimization());
|
||||
result->ReplaceCode(code);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isolate()->use_crankshaft() &&
|
||||
FLAG_always_opt &&
|
||||
result->is_compiled() &&
|
||||
!info->is_toplevel() &&
|
||||
info->allows_lazy_compilation() &&
|
||||
!info->optimization_disabled() &&
|
||||
!isolate()->DebuggerHasBreakPoints()) {
|
||||
result->MarkForOptimization();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> Factory::NewNumber(double value,
|
||||
PretenureFlag pretenure) {
|
||||
// We need to distinguish the minus zero value and this cannot be
|
||||
@ -1256,6 +1177,62 @@ Handle<Object> Factory::NewError(const char* constructor,
|
||||
}
|
||||
|
||||
|
||||
void Factory::InitializeFunction(Handle<JSFunction> function,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context) {
|
||||
function->initialize_properties();
|
||||
function->initialize_elements();
|
||||
function->set_shared(*info);
|
||||
function->set_code(info->code());
|
||||
function->set_context(*context);
|
||||
function->set_prototype_or_initial_map(*the_hole_value());
|
||||
function->set_literals_or_bindings(*empty_fixed_array());
|
||||
function->set_next_function_link(*undefined_value());
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
PretenureFlag pretenure) {
|
||||
AllocationSpace space = pretenure == TENURED ? OLD_POINTER_SPACE : NEW_SPACE;
|
||||
Handle<JSFunction> result = New<JSFunction>(map, space);
|
||||
InitializeFunction(result, info, context);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
Handle<Code> code,
|
||||
MaybeHandle<Object> maybe_prototype) {
|
||||
Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name);
|
||||
ASSERT(info->strict_mode() == SLOPPY);
|
||||
info->set_code(*code);
|
||||
Handle<Context> context(isolate()->context()->native_context());
|
||||
Handle<Map> map = maybe_prototype.is_null()
|
||||
? isolate()->sloppy_function_without_prototype_map()
|
||||
: isolate()->sloppy_function_map();
|
||||
Handle<JSFunction> result = NewFunction(map, info, context);
|
||||
Handle<Object> prototype;
|
||||
if (maybe_prototype.ToHandle(&prototype)) {
|
||||
result->set_prototype_or_initial_map(*prototype);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
|
||||
Handle<Object> prototype) {
|
||||
Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name);
|
||||
ASSERT(info->strict_mode() == SLOPPY);
|
||||
Handle<Context> context(isolate()->context()->native_context());
|
||||
Handle<Map> map = isolate()->sloppy_function_map();
|
||||
Handle<JSFunction> result = NewFunction(map, info, context);
|
||||
result->set_prototype_or_initial_map(*prototype);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(MaybeHandle<Object> maybe_prototype,
|
||||
Handle<String> name,
|
||||
InstanceType type,
|
||||
@ -1326,6 +1303,87 @@ Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
|
||||
// Make sure to use globals from the function's context, since the function
|
||||
// can be from a different context.
|
||||
Handle<Context> native_context(function->context()->native_context());
|
||||
Handle<Map> new_map;
|
||||
if (function->shared()->is_generator()) {
|
||||
// Generator prototypes can share maps since they don't have "constructor"
|
||||
// properties.
|
||||
new_map = handle(native_context->generator_object_prototype_map());
|
||||
} else {
|
||||
// Each function prototype gets a fresh map to avoid unwanted sharing of
|
||||
// maps between prototypes of different constructors.
|
||||
Handle<JSFunction> object_function(native_context->object_function());
|
||||
ASSERT(object_function->has_initial_map());
|
||||
new_map = Map::Copy(handle(object_function->initial_map()));
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
|
||||
|
||||
if (!function->shared()->is_generator()) {
|
||||
JSObject::SetLocalPropertyIgnoreAttributes(prototype,
|
||||
constructor_string(),
|
||||
function,
|
||||
DONT_ENUM).Assert();
|
||||
}
|
||||
|
||||
return prototype;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
PretenureFlag pretenure) {
|
||||
int map_index = Context::FunctionMapIndex(info->strict_mode(),
|
||||
info->is_generator());
|
||||
Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
|
||||
Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
|
||||
|
||||
if (info->ic_age() != isolate()->heap()->global_ic_age()) {
|
||||
info->ResetForNewContext(isolate()->heap()->global_ic_age());
|
||||
}
|
||||
|
||||
int index = info->SearchOptimizedCodeMap(context->native_context(),
|
||||
BailoutId::None());
|
||||
if (!info->bound() && index < 0) {
|
||||
int number_of_literals = info->num_literals();
|
||||
Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
|
||||
if (number_of_literals > 0) {
|
||||
// Store the native context in the literals array prefix. This
|
||||
// context will be used when creating object, regexp and array
|
||||
// literals in this function.
|
||||
literals->set(JSFunction::kLiteralNativeContextIndex,
|
||||
context->native_context());
|
||||
}
|
||||
result->set_literals(*literals);
|
||||
}
|
||||
|
||||
if (index > 0) {
|
||||
// Caching of optimized code enabled and optimized code found.
|
||||
FixedArray* literals = info->GetLiteralsFromOptimizedCodeMap(index);
|
||||
if (literals != NULL) result->set_literals(literals);
|
||||
Code* code = info->GetCodeFromOptimizedCodeMap(index);
|
||||
ASSERT(!code->marked_for_deoptimization());
|
||||
result->ReplaceCode(code);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isolate()->use_crankshaft() &&
|
||||
FLAG_always_opt &&
|
||||
result->is_compiled() &&
|
||||
!info->is_toplevel() &&
|
||||
info->allows_lazy_compilation() &&
|
||||
!info->optimization_disabled() &&
|
||||
!isolate()->DebuggerHasBreakPoints()) {
|
||||
result->MarkForOptimization();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSObject> Factory::NewIteratorResultObject(Handle<Object> value,
|
||||
bool done) {
|
||||
Handle<Map> map(isolate()->native_context()->iterator_result_map());
|
||||
@ -1759,8 +1817,7 @@ void Factory::ReinitializeJSReceiver(Handle<JSReceiver> object,
|
||||
map->set_function_with_prototype(true);
|
||||
Handle<JSFunction> js_function = Handle<JSFunction>::cast(object);
|
||||
Handle<Context> context(isolate()->context()->native_context());
|
||||
InitializeFunction(js_function, shared.ToHandleChecked(),
|
||||
context, null_value());
|
||||
InitializeFunction(js_function, shared.ToHandleChecked(), context);
|
||||
}
|
||||
|
||||
// Put in filler if the new object is smaller than the old.
|
||||
@ -1994,73 +2051,6 @@ Handle<String> Factory::NumberToString(Handle<Object> number,
|
||||
}
|
||||
|
||||
|
||||
void Factory::InitializeFunction(Handle<JSFunction> function,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
MaybeHandle<Object> maybe_prototype) {
|
||||
function->initialize_properties();
|
||||
function->initialize_elements();
|
||||
function->set_shared(*info);
|
||||
function->set_code(info->code());
|
||||
function->set_context(*context);
|
||||
Handle<Object> prototype;
|
||||
if (maybe_prototype.ToHandle(&prototype)) {
|
||||
ASSERT(!prototype->IsMap());
|
||||
} else {
|
||||
prototype = the_hole_value();
|
||||
}
|
||||
function->set_prototype_or_initial_map(*prototype);
|
||||
function->set_literals_or_bindings(*empty_fixed_array());
|
||||
function->set_next_function_link(*undefined_value());
|
||||
}
|
||||
|
||||
|
||||
static Handle<Map> MapForNewFunction(Isolate* isolate,
|
||||
Handle<SharedFunctionInfo> function_info,
|
||||
MaybeHandle<Object> maybe_prototype) {
|
||||
if (maybe_prototype.is_null()) {
|
||||
return function_info->strict_mode() == SLOPPY
|
||||
? isolate->sloppy_function_without_prototype_map()
|
||||
: isolate->strict_function_without_prototype_map();
|
||||
}
|
||||
|
||||
Context* context = isolate->context()->native_context();
|
||||
int map_index = Context::FunctionMapIndex(function_info->strict_mode(),
|
||||
function_info->is_generator());
|
||||
return Handle<Map>(Map::cast(context->get(map_index)));
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
MaybeHandle<Object> maybe_prototype,
|
||||
PretenureFlag pretenure) {
|
||||
Handle<Map> map = MapForNewFunction(isolate(), info, maybe_prototype);
|
||||
AllocationSpace space = pretenure == TENURED ? OLD_POINTER_SPACE : NEW_SPACE;
|
||||
Handle<JSFunction> result = New<JSFunction>(map, space);
|
||||
InitializeFunction(result, info, context, maybe_prototype);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
Handle<Code> code,
|
||||
MaybeHandle<Object> maybe_prototype) {
|
||||
Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name);
|
||||
info->set_code(*code);
|
||||
Handle<Context> context(isolate()->context()->native_context());
|
||||
return NewFunction(info, context, maybe_prototype);
|
||||
}
|
||||
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
|
||||
Handle<Object> prototype) {
|
||||
Handle<SharedFunctionInfo> info = NewSharedFunctionInfo(name);
|
||||
Handle<Context> context(isolate()->context()->native_context());
|
||||
return NewFunction(info, context, prototype);
|
||||
}
|
||||
|
||||
|
||||
Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
|
||||
// Get the original code of the function.
|
||||
Handle<Code> code(shared->code());
|
||||
|
@ -676,13 +676,12 @@ class Factory V8_FINAL {
|
||||
// type JS_FUNCTION_TYPE benefit from the use of this function.
|
||||
inline void InitializeFunction(Handle<JSFunction> function,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
MaybeHandle<Object> maybe_prototype);
|
||||
Handle<Context> context);
|
||||
|
||||
// Creates a function initialized with a shared part.
|
||||
inline Handle<JSFunction> NewFunction(Handle<SharedFunctionInfo> info,
|
||||
inline Handle<JSFunction> NewFunction(Handle<Map> map,
|
||||
Handle<SharedFunctionInfo> info,
|
||||
Handle<Context> context,
|
||||
MaybeHandle<Object> maybe_prototype,
|
||||
PretenureFlag pretenure = TENURED);
|
||||
|
||||
// Create a new map cache.
|
||||
|
Loading…
Reference in New Issue
Block a user