JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return Smi::FromInt(0);
// Check if already compiled.
- if (!function->is_compiled()) {
+ if (!function->shared()->is_compiled()) {
// If the function isn't compiled yet, the length is not computed
// correctly yet. Compile it now and return the right length.
HandleScope scope;
__ ldr(r2,
FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
__ mov(r2, Operand(r2, ASR, kSmiTagSize));
- __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
+ __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeOffset));
__ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
__ cmp(r2, r0); // Check formal and actual parameter counts.
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
__ BranchOnSmi(r0, &build_args);
__ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
__ b(ne, &build_args);
- __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
- __ ldr(r1, FieldMemOperand(r0, SharedFunctionInfo::kCodeOffset));
+ __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeOffset));
__ cmp(r1, Operand(apply_code));
__ b(ne, &build_args);
__ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
__ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
+ // Initialize the code pointer in the function to be the one
+ // found in the shared function info object.
+ __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
+ __ str(r3, FieldMemOperand(r0, JSFunction::kCodeOffset));
+
// Return result. The argument function info has been popped already.
__ Ret();
SharedFunctionInfo::kFormalParameterCountOffset));
mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize));
ldr(code_reg,
- MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
+ MemOperand(r1, JSFunction::kCodeOffset - kHeapObjectTag));
add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
ParameterCount expected(expected_reg);
// Make sure the code objects in the builtins object and in the
// builtin function are the same.
push(r1);
- ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
- ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
+ ldr(r1, FieldMemOperand(r1, JSFunction::kCodeOffset));
cmp(r1, target);
Assert(eq, "Builtin code object changed");
pop(r1);
Handle<Code> code =
Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
empty_function->set_code(*code);
+ empty_function->shared()->set_code(*code);
Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
Handle<Script> script = Factory::NewScript(source);
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
Handle<SharedFunctionInfo> shared
= Handle<SharedFunctionInfo>(function->shared());
if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false;
+ // Set the code object on the function object.
+ function->set_code(function->shared()->code());
builtins->set_javascript_builtin_code(id, shared->code());
}
return true;
bool force_initial_map) {
// Allocate the function
Handle<JSFunction> function = NewFunction(name, the_hole_value());
+
+ // Setup the code pointer in both the shared function info and in
+ // the function itself.
+ function->shared()->set_code(*code);
function->set_code(*code);
if (force_initial_map ||
Handle<JSObject> prototype,
Handle<Code> code,
bool force_initial_map) {
- // Allocate the function
+ // Allocate the function.
Handle<JSFunction> function = NewFunction(name, prototype);
+ // Setup the code pointer in both the shared function info and in
+ // the function itself.
+ function->shared()->set_code(*code);
function->set_code(*code);
if (force_initial_map ||
Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name,
Handle<Code> code) {
Handle<JSFunction> function = NewFunctionWithoutPrototype(name);
+ function->shared()->set_code(*code);
function->set_code(*code);
ASSERT(!function->has_initial_map());
ASSERT(!function->has_prototype());
bool CompileLazy(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
- CompilationInfo info(function, 0, receiver);
- bool result = CompileLazyHelper(&info, flag);
- PROFILE(FunctionCreateEvent(*function));
- return result;
+ if (function->shared()->is_compiled()) {
+ function->set_code(function->shared()->code());
+ return true;
+ } else {
+ CompilationInfo info(function, 0, receiver);
+ bool result = CompileLazyHelper(&info, flag);
+ PROFILE(FunctionCreateEvent(*function));
+ return result;
+ }
}
bool CompileLazyInLoop(Handle<JSFunction> function,
Handle<Object> receiver,
ClearExceptionFlag flag) {
- CompilationInfo info(function, 1, receiver);
- bool result = CompileLazyHelper(&info, flag);
- PROFILE(FunctionCreateEvent(*function));
- return result;
+ if (function->shared()->is_compiled()) {
+ function->set_code(function->shared()->code());
+ return true;
+ } else {
+ CompilationInfo info(function, 1, receiver);
+ bool result = CompileLazyHelper(&info, flag);
+ PROFILE(FunctionCreateEvent(*function));
+ return result;
+ }
}
};
-static void FlushCodeForFunction(SharedFunctionInfo* function_info) {
+static bool CodeIsActive(Code* code) {
+ // Make sure we are not referencing the code from the stack.
+ for (StackFrameIterator it; !it.done(); it.Advance()) {
+ if (code->contains(it.frame()->pc())) return true;
+ }
+ // Iterate the archived stacks in all threads to check if
+ // the code is referenced.
+ FlushingStackVisitor threadvisitor(code);
+ ThreadManager::IterateArchivedThreads(&threadvisitor);
+ if (threadvisitor.FoundCode()) return true;
+ return false;
+}
+
+
+static void FlushCodeForFunction(JSFunction* function) {
+ SharedFunctionInfo* shared_info = function->shared();
+
+ // Special handling if the function and shared info objects
+ // have different code objects.
+ if (function->code() != shared_info->code()) {
+ // If the shared function has been flushed but the function has not,
+ // we flush the function if possible.
+ if (!shared_info->is_compiled() && function->is_compiled() &&
+ !CodeIsActive(function->code())) {
+ function->set_code(shared_info->code());
+ }
+ return;
+ }
+
// The function must be compiled and have the source code available,
// to be able to recompile it in case we need the function again.
- if (!(function_info->is_compiled() && function_info->HasSourceCode())) return;
+ if (!(shared_info->is_compiled() && shared_info->HasSourceCode())) return;
// We never flush code for Api functions.
- if (function_info->IsApiFunction()) return;
+ if (shared_info->IsApiFunction()) return;
// Only flush code for functions.
- if (!function_info->code()->kind() == Code::FUNCTION) return;
+ if (!shared_info->code()->kind() == Code::FUNCTION) return;
// Function must be lazy compilable.
- if (!function_info->allows_lazy_compilation()) return;
+ if (!shared_info->allows_lazy_compilation()) return;
// If this is a full script wrapped in a function we do no flush the code.
- if (function_info->is_toplevel()) return;
+ if (shared_info->is_toplevel()) return;
// If this function is in the compilation cache we do not flush the code.
- if (CompilationCache::HasFunction(function_info)) return;
+ if (CompilationCache::HasFunction(shared_info)) return;
- // Make sure we are not referencing the code from the stack.
- for (StackFrameIterator it; !it.done(); it.Advance()) {
- if (function_info->code()->contains(it.frame()->pc())) return;
- }
- // Iterate the archived stacks in all threads to check if
- // the code is referenced.
- FlushingStackVisitor threadvisitor(function_info->code());
- ThreadManager::IterateArchivedThreads(&threadvisitor);
- if (threadvisitor.FoundCode()) return;
+ // Check stack and archived threads for the code.
+ if (CodeIsActive(shared_info->code())) return;
// Compute the lazy compilable version of the code.
HandleScope scope;
- function_info->set_code(*ComputeLazyCompile(function_info->length()));
+ Code* code = *ComputeLazyCompile(shared_info->length());
+ shared_info->set_code(code);
+ function->set_code(code);
}
HeapObjectIterator it(old_pointer_space());
for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
if (obj->IsJSFunction()) {
- JSFunction* jsfunction = JSFunction::cast(obj);
+ JSFunction* function = JSFunction::cast(obj);
// The function must have a valid context and not be a builtin.
- if (jsfunction->unchecked_context()->IsContext() &&
- !jsfunction->IsBuiltin()) {
- FlushCodeForFunction(jsfunction->shared());
+ if (function->unchecked_context()->IsContext() &&
+ !function->IsBuiltin()) {
+ FlushCodeForFunction(function);
}
}
}
function->initialize_properties();
function->initialize_elements();
function->set_shared(shared);
+ function->set_code(shared->code());
function->set_prototype_or_initial_map(prototype);
function->set_context(undefined_value());
function->set_literals(empty_fixed_array());
__ mov(ebx,
FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
__ SmiUntag(ebx);
- __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+ __ mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
__ lea(edx, FieldOperand(edx, Code::kHeaderSize));
__ cmp(eax, Operand(ebx));
__ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));
__ j(zero, &build_args);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &build_args);
- __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
- __ cmp(FieldOperand(ecx, SharedFunctionInfo::kCodeOffset),
- Immediate(apply_code));
+ __ cmp(FieldOperand(eax, JSFunction::kCodeOffset), Immediate(apply_code));
__ j(not_equal, &build_args);
// Check that applicand is a function.
__ mov(FieldOperand(eax, JSFunction::kContextOffset), esi);
__ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx);
+ // Initialize the code pointer in the function to be the one
+ // found in the shared function info object.
+ __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+ __ mov(FieldOperand(eax, JSFunction::kCodeOffset), edx);
+
// Return and remove the on-stack parameter.
__ ret(1 * kPointerSize);
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
SmiUntag(ebx);
- mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+ mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
lea(edx, FieldOperand(edx, Code::kHeaderSize));
ParameterCount expected(ebx);
// Make sure the code objects in the builtins object and in the
// builtin function are the same.
push(target);
- mov(target, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
- mov(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset));
+ mov(target, FieldOperand(edi, JSFunction::kCodeOffset));
cmp(target, Operand(esp, 0));
Assert(equal, "Builtin code object changed");
pop(target);
Code* JSFunction::code() {
- return shared()->code();
+ return Code::cast(READ_FIELD(this, kCodeOffset));
}
void JSFunction::set_code(Code* value) {
- shared()->set_code(value);
+ // Skip the write barrier because code is never in new space.
+ ASSERT(!Heap::InNewSpace(value));
+ WRITE_FIELD(this, kCodeOffset, value);
}
bool JSFunction::is_compiled() {
- return shared()->is_compiled();
+ return code()->kind() != Code::STUB;
}
static Context* GlobalContextFromLiterals(FixedArray* literals);
// Layout descriptors.
- static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize;
+ static const int kCodeOffset = JSObject::kHeaderSize;
+ static const int kPrototypeOrInitialMapOffset =
+ kCodeOffset + kPointerSize;
static const int kSharedFunctionInfoOffset =
kPrototypeOrInitialMapOffset + kPointerSize;
static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
}
// Set the code, scope info, formal parameter count,
// and the length of the target function.
- target->set_code(fun->code());
+ target->shared()->set_code(shared->code());
+ target->set_code(shared->code());
target->shared()->set_scope_info(shared->scope_info());
target->shared()->set_length(shared->length());
target->shared()->set_formal_parameter_count(
Handle<JSFunction> function = args.at<JSFunction>(0);
#ifdef DEBUG
- if (FLAG_trace_lazy) {
+ if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
PrintF("[lazy: ");
function->shared()->name()->Print();
PrintF("]\n");
}
static int partial_snapshot_cache_length_;
- static const int kPartialSnapshotCacheCapacity = 1300;
+ static const int kPartialSnapshotCacheCapacity = 1350;
static Object* partial_snapshot_cache_[];
};
__ movsxlq(rbx,
FieldOperand(rdx,
SharedFunctionInfo::kFormalParameterCountOffset));
- __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+ __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
__ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
__ cmpq(rax, rbx);
__ j(not_equal,
__ j(is_smi, &build_args);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &build_args);
- __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
- __ Cmp(FieldOperand(rax, SharedFunctionInfo::kCodeOffset), apply_code);
+ __ Cmp(FieldOperand(rax, JSFunction::kCodeOffset), apply_code);
__ j(not_equal, &build_args);
// Check that applicand is a function.
__ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi);
__ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx);
+ // Initialize the code pointer in the function to be the one
+ // found in the shared function info object.
+ __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+ __ movq(FieldOperand(rax, JSFunction::kCodeOffset), rdx);
+
+
// Return and remove the on-stack parameter.
__ ret(1 * kPointerSize);
// Make sure the code objects in the builtins object and in the
// builtin function are the same.
push(target);
- movq(target, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
- movq(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset));
+ movq(target, FieldOperand(rdi, JSFunction::kCodeOffset));
cmpq(target, Operand(rsp, 0));
Assert(equal, "Builtin code object changed");
pop(target);
movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
movsxlq(rbx,
FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
- movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+ movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
// Advances rdx to the end of the Code object header, to the start of
// the executable code.
lea(rdx, FieldOperand(rdx, Code::kHeaderSize));