// Create a new closure through the slower runtime call.
__ bind(&gc);
- __ Push(cp, r3);
- __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
+ __ LoadRoot(r4, Heap::kFalseValueRootIndex);
+ __ Push(cp, r3, r4);
+ __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
}
void CodeGenerator::InstantiateFunction(
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ bool pretenure) {
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
- if (scope()->is_function_scope() && function_info->num_literals() == 0) {
+ if (scope()->is_function_scope() &&
+ function_info->num_literals() == 0 &&
+ !pretenure) {
FastNewClosureStub stub;
frame_->EmitPush(Operand(function_info));
frame_->SpillAll();
// Create a new closure.
frame_->EmitPush(cp);
frame_->EmitPush(Operand(function_info));
- frame_->CallRuntime(Runtime::kNewClosure, 2);
+ frame_->EmitPush(Operand(pretenure
+ ? Factory::true_value()
+ : Factory::false_value()));
+ frame_->CallRuntime(Runtime::kNewClosure, 3);
frame_->EmitPush(r0);
}
}
ASSERT(frame_->height() == original_height);
return;
}
- InstantiateFunction(function_info);
+ InstantiateFunction(function_info, node->pretenure());
ASSERT_EQ(original_height + 1, frame_->height());
}
int original_height = frame_->height();
#endif
Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
- InstantiateFunction(node->shared_function_info());
+ InstantiateFunction(node->shared_function_info(), false);
ASSERT_EQ(original_height + 1, frame_->height());
}
void DeclareGlobals(Handle<FixedArray> pairs);
// Instantiate the function based on the shared function info.
- void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
+ void InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+ bool pretenure);
// Support for type checks.
void GenerateIsSmi(ZoneList<Expression*>* args);
}
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+ bool pretenure) {
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
- if (scope()->is_function_scope() && info->num_literals() == 0) {
+ if (scope()->is_function_scope() &&
+ info->num_literals() == 0 &&
+ !pretenure) {
FastNewClosureStub stub;
__ mov(r0, Operand(info));
__ push(r0);
__ CallStub(&stub);
} else {
__ mov(r0, Operand(info));
- __ Push(cp, r0);
- __ CallRuntime(Runtime::kNewClosure, 2);
+ __ LoadRoot(r1, pretenure ? Heap::kTrueValueRootIndex
+ : Heap::kFalseValueRootIndex);
+ __ Push(cp, r0, r1);
+ __ CallRuntime(Runtime::kNewClosure, 3);
}
context()->Plug(r0);
}
contains_loops_(contains_loops),
function_token_position_(RelocInfo::kNoPosition),
inferred_name_(Heap::empty_string()),
- try_full_codegen_(false) {
+ try_full_codegen_(false),
+ pretenure_(false) {
#ifdef DEBUG
already_compiled_ = false;
#endif
bool try_full_codegen() { return try_full_codegen_; }
void set_try_full_codegen(bool flag) { try_full_codegen_ = flag; }
+ bool pretenure() { return pretenure_; }
+ void set_pretenure(bool value) { pretenure_ = value; }
+
#ifdef DEBUG
void mark_as_compiled() {
ASSERT(!already_compiled_);
int function_token_position_;
Handle<String> inferred_name_;
bool try_full_codegen_;
+ bool pretenure_;
#ifdef DEBUG
bool already_compiled_;
#endif
SetStackOverflow();
return;
}
- EmitNewClosure(function_info);
+ EmitNewClosure(function_info, expr->pretenure());
}
void FullCodeGenerator::VisitSharedFunctionInfoLiteral(
SharedFunctionInfoLiteral* expr) {
Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
- EmitNewClosure(expr->shared_function_info());
+ EmitNewClosure(expr->shared_function_info(), false);
}
// Platform-specific support for allocating a new closure based on
// the given function info.
- void EmitNewClosure(Handle<SharedFunctionInfo> info);
+ void EmitNewClosure(Handle<SharedFunctionInfo> info, bool pretenure);
// Platform-specific support for compiling assignments.
__ pop(edx);
__ push(esi);
__ push(edx);
+ __ push(Immediate(Factory::false_value()));
__ push(ecx); // Restore return address.
- __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
+ __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
}
Result CodeGenerator::InstantiateFunction(
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ bool pretenure) {
// The inevitable call will sync frame elements to memory anyway, so
// we do it eagerly to allow us to push the arguments directly into
// place.
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
- if (scope()->is_function_scope() && function_info->num_literals() == 0) {
+ if (scope()->is_function_scope() &&
+ function_info->num_literals() == 0 &&
+ !pretenure) {
FastNewClosureStub stub;
frame()->EmitPush(Immediate(function_info));
return frame()->CallStub(&stub, 1);
// shared function info.
frame()->EmitPush(esi);
frame()->EmitPush(Immediate(function_info));
- return frame()->CallRuntime(Runtime::kNewClosure, 2);
+ frame()->EmitPush(Immediate(pretenure
+ ? Factory::true_value()
+ : Factory::false_value()));
+ return frame()->CallRuntime(Runtime::kNewClosure, 3);
}
}
SetStackOverflow();
return;
}
- Result result = InstantiateFunction(function_info);
+ Result result = InstantiateFunction(function_info, node->pretenure());
frame()->Push(&result);
}
SharedFunctionInfoLiteral* node) {
ASSERT(!in_safe_int32_mode());
Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
- Result result = InstantiateFunction(node->shared_function_info());
+ Result result = InstantiateFunction(node->shared_function_info(), false);
frame()->Push(&result);
}
void DeclareGlobals(Handle<FixedArray> pairs);
// Instantiate the function based on the shared function info.
- Result InstantiateFunction(Handle<SharedFunctionInfo> function_info);
+ Result InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+ bool pretenure);
// Support for types.
void GenerateIsSmi(ZoneList<Expression*>* args);
}
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+ bool pretenure) {
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
- if (scope()->is_function_scope() && info->num_literals() == 0) {
+ if (scope()->is_function_scope() &&
+ info->num_literals() == 0 &&
+ !pretenure) {
FastNewClosureStub stub;
__ push(Immediate(info));
__ CallStub(&stub);
} else {
__ push(esi);
__ push(Immediate(info));
- __ CallRuntime(Runtime::kNewClosure, 2);
+ __ push(Immediate(pretenure
+ ? Factory::true_value()
+ : Factory::false_value()));
+ __ CallRuntime(Runtime::kNewClosure, 3);
}
context()->Plug(eax);
}
temp_scope_->AddProperty();
}
+ // If we assign a function literal to a property we pretenure the
+ // literal so it can be added as a constant function property.
+ if (property != NULL && right->AsFunctionLiteral() != NULL) {
+ right->AsFunctionLiteral()->set_pretenure(true);
+ }
+
if (fni_ != NULL) {
// Check if the right hand side is a call to avoid inferring a
// name if we're dealing with "a = function(){...}();"-like
static MaybeObject* Runtime_NewClosure(Arguments args) {
HandleScope scope;
- ASSERT(args.length() == 2);
+ ASSERT(args.length() == 3);
CONVERT_ARG_CHECKED(Context, context, 0);
CONVERT_ARG_CHECKED(SharedFunctionInfo, shared, 1);
+ CONVERT_BOOLEAN_CHECKED(pretenure, args[2]);
- PretenureFlag pretenure = (context->global_context() == *context)
- ? TENURED // Allocate global closures in old space.
- : NOT_TENURED; // Allocate local closures in new space.
+ // Allocate global closures in old space and allocate local closures
+ // in new space. Additionally pretenure closures that are assigned
+ // directly to properties.
+ pretenure = pretenure || (context->global_context() == *context);
+ PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
Handle<JSFunction> result =
- Factory::NewFunctionFromSharedFunctionInfo(shared, context, pretenure);
+ Factory::NewFunctionFromSharedFunctionInfo(shared,
+ context,
+ pretenure_flag);
return *result;
}
F(CreateCatchExtensionObject, 2, 1) \
\
/* Statements */ \
- F(NewClosure, 2, 1) \
+ F(NewClosure, 3, 1) \
F(NewObject, 1, 1) \
F(NewObjectFromBound, 2, 1) \
F(FinalizeInstanceSize, 1, 1) \
__ pop(rdx);
__ push(rsi);
__ push(rdx);
+ __ Push(Factory::false_value());
__ push(rcx); // Restore return address.
- __ TailCallRuntime(Runtime::kNewClosure, 2, 1);
+ __ TailCallRuntime(Runtime::kNewClosure, 3, 1);
}
void CodeGenerator::InstantiateFunction(
- Handle<SharedFunctionInfo> function_info) {
+ Handle<SharedFunctionInfo> function_info,
+ bool pretenure) {
// The inevitable call will sync frame elements to memory anyway, so
// we do it eagerly to allow us to push the arguments directly into
// place.
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
- if (scope()->is_function_scope() && function_info->num_literals() == 0) {
+ if (scope()->is_function_scope() &&
+ function_info->num_literals() == 0 &&
+ !pretenure) {
FastNewClosureStub stub;
frame_->Push(function_info);
Result answer = frame_->CallStub(&stub, 1);
// shared function info.
frame_->EmitPush(rsi);
frame_->EmitPush(function_info);
- Result result = frame_->CallRuntime(Runtime::kNewClosure, 2);
+ frame_->EmitPush(pretenure
+ ? Factory::true_value()
+ : Factory::false_value());
+ Result result = frame_->CallRuntime(Runtime::kNewClosure, 3);
frame_->Push(&result);
}
}
SetStackOverflow();
return;
}
- InstantiateFunction(function_info);
+ InstantiateFunction(function_info, node->pretenure());
}
void CodeGenerator::VisitSharedFunctionInfoLiteral(
SharedFunctionInfoLiteral* node) {
Comment cmnt(masm_, "[ SharedFunctionInfoLiteral");
- InstantiateFunction(node->shared_function_info());
+ InstantiateFunction(node->shared_function_info(), false);
}
void DeclareGlobals(Handle<FixedArray> pairs);
// Instantiate the function based on the shared function info.
- void InstantiateFunction(Handle<SharedFunctionInfo> function_info);
+ void InstantiateFunction(Handle<SharedFunctionInfo> function_info,
+ bool pretenure);
// Support for type checks.
void GenerateIsSmi(ZoneList<Expression*>* args);
}
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info) {
+void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
+ bool pretenure) {
// Use the fast case closure allocation code that allocates in new
// space for nested functions that don't need literals cloning.
- if (scope()->is_function_scope() && info->num_literals() == 0) {
+ if (scope()->is_function_scope() &&
+ info->num_literals() == 0 &&
+ !pretenure) {
FastNewClosureStub stub;
__ Push(info);
__ CallStub(&stub);
} else {
__ push(rsi);
__ Push(info);
- __ CallRuntime(Runtime::kNewClosure, 2);
+ __ Push(pretenure ? Factory::true_value() : Factory::false_value());
+ __ CallRuntime(Runtime::kNewClosure, 3);
}
context()->Plug(rax);
}