Change code pointer in function objects to a pointer to the first

instruction.

By changing the pointer to the code object to a pointer to the first
instruction we can call directly this instruction directly instead of
looking up the address through the code object.

Review URL: http://codereview.chromium.org/3156028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5309 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ricow@chromium.org 2010-08-20 07:10:18 +00:00
parent 103d7c7993
commit 2982f5e320
19 changed files with 190 additions and 97 deletions

View File

@ -1073,8 +1073,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ ldr(r2,
FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
__ mov(r2, Operand(r2, ASR, kSmiTagSize));
__ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeOffset));
__ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
__ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
__ cmp(r2, r0); // Check formal and actual parameter counts.
__ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
RelocInfo::CODE_TARGET, ne);

View File

@ -1556,7 +1556,8 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
__ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
__ b(ne, &build_args);
Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
__ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeOffset));
__ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
__ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ cmp(r1, Operand(apply_code));
__ b(ne, &build_args);
@ -7028,7 +7029,8 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
// 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));
__ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
__ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
// Return result. The argument function info has been popped already.
__ Ret();

View File

@ -757,8 +757,7 @@ void MacroAssembler::InvokeFunction(Register fun,
SharedFunctionInfo::kFormalParameterCountOffset));
mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize));
ldr(code_reg,
MemOperand(r1, JSFunction::kCodeOffset - kHeapObjectTag));
add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
ParameterCount expected(expected_reg);
InvokeCode(code_reg, expected, actual, flag);
@ -1490,30 +1489,22 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
ASSERT(!target.is(r1));
void MacroAssembler::GetBuiltinFunction(Register target,
Builtins::JavaScript id) {
// Load the builtins object into target register.
ldr(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
// Load the JavaScript builtin function from the builtins object.
ldr(r1, FieldMemOperand(target,
JSBuiltinsObject::OffsetOfFunctionWithId(id)));
// Load the code entry point from the builtins object.
ldr(target, FieldMemOperand(target,
JSBuiltinsObject::OffsetOfCodeWithId(id)));
if (FLAG_debug_code) {
// Make sure the code objects in the builtins object and in the
// builtin function are the same.
push(r1);
ldr(r1, FieldMemOperand(r1, JSFunction::kCodeOffset));
cmp(r1, target);
Assert(eq, "Builtin code object changed");
pop(r1);
}
add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
JSBuiltinsObject::OffsetOfFunctionWithId(id)));
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
ASSERT(!target.is(r1));
GetBuiltinFunction(r1, id);
// Load the code entry point from the builtins object.
ldr(target, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
}

View File

@ -576,6 +576,9 @@ class MacroAssembler: public Assembler {
// setup the function in r1.
void GetBuiltinEntry(Register target, Builtins::JavaScript id);
// Store the function for the given builtin in the target register.
void GetBuiltinFunction(Register target, Builtins::JavaScript id);
Handle<Object> CodeObject() { return code_object_; }

View File

@ -567,9 +567,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(ebx,
FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
__ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
__ SmiUntag(ebx);
__ mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
__ lea(edx, FieldOperand(edx, Code::kHeaderSize));
__ cmp(eax, Operand(ebx));
__ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));

View File

@ -3423,8 +3423,10 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
__ j(zero, &build_args);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx);
__ j(not_equal, &build_args);
__ mov(ecx, FieldOperand(eax, JSFunction::kCodeEntryOffset));
__ sub(Operand(ecx), Immediate(Code::kHeaderSize - kHeapObjectTag));
Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
__ cmp(FieldOperand(eax, JSFunction::kCodeOffset), Immediate(apply_code));
__ cmp(Operand(ecx), Immediate(apply_code));
__ j(not_equal, &build_args);
// Check that applicand is a function.
@ -9815,7 +9817,8 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
// 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);
__ lea(edx, FieldOperand(edx, Code::kHeaderSize));
__ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx);
// Return and remove the on-stack parameter.
__ ret(1 * kPointerSize);

View File

@ -1298,11 +1298,10 @@ void MacroAssembler::InvokeFunction(Register fun,
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
SmiUntag(ebx);
mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
lea(edx, FieldOperand(edx, Code::kHeaderSize));
ParameterCount expected(ebx);
InvokeCode(Operand(edx), expected, actual, flag);
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, actual, flag);
}
@ -1313,7 +1312,6 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
// Get the function and setup the context.
mov(edi, Immediate(Handle<JSFunction>(function)));
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// Invoke the cached code.
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
@ -1329,33 +1327,26 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
// arguments match the expected number of arguments. Fake a
// parameter count to avoid emitting code to do the check.
ParameterCount expected(0);
GetBuiltinEntry(edx, id);
InvokeCode(Operand(edx), expected, expected, flag);
GetBuiltinFunction(edi, id);
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, expected, flag);
}
void MacroAssembler::GetBuiltinFunction(Register target,
Builtins::JavaScript id) {
// Load the JavaScript builtin function from the builtins object.
mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
mov(target, FieldOperand(target,
JSBuiltinsObject::OffsetOfFunctionWithId(id)));
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
ASSERT(!target.is(edi));
// Load the builtins object into target register.
mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
// Load the JavaScript builtin function from the builtins object.
mov(edi, FieldOperand(target, JSBuiltinsObject::OffsetOfFunctionWithId(id)));
// Load the code entry point from the builtins object.
mov(target, FieldOperand(target, JSBuiltinsObject::OffsetOfCodeWithId(id)));
if (FLAG_debug_code) {
// Make sure the code objects in the builtins object and in the
// builtin function are the same.
push(target);
mov(target, FieldOperand(edi, JSFunction::kCodeOffset));
cmp(target, Operand(esp, 0));
Assert(equal, "Builtin code object changed");
pop(target);
}
lea(target, FieldOperand(target, Code::kHeaderSize));
GetBuiltinFunction(edi, id);
// Load the code entry point from the function into the target register.
mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset));
}

View File

@ -169,6 +169,9 @@ class MacroAssembler: public Assembler {
// the unresolved list if the name does not resolve.
void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
// Store the function for the given builtin in the target register.
void GetBuiltinFunction(Register target, Builtins::JavaScript id);
// Store the code object for the given builtin in the target register.
void GetBuiltinEntry(Register target, Builtins::JavaScript id);

View File

@ -750,7 +750,7 @@ void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
class ReferenceCollectorVisitor : public ObjectVisitor {
public:
explicit ReferenceCollectorVisitor(Code* original)
: original_(original), rvalues_(10), reloc_infos_(10) {
: original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
}
virtual void VisitPointers(Object** start, Object** end) {
@ -761,7 +761,13 @@ class ReferenceCollectorVisitor : public ObjectVisitor {
}
}
void VisitCodeTarget(RelocInfo* rinfo) {
virtual void VisitCodeEntry(Address entry) {
if (Code::GetObjectFromEntryAddress(entry) == original_) {
code_entries_.Add(entry);
}
}
virtual void VisitCodeTarget(RelocInfo* rinfo) {
if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
reloc_infos_.Add(*rinfo);
@ -778,8 +784,13 @@ class ReferenceCollectorVisitor : public ObjectVisitor {
for (int i = 0; i < rvalues_.length(); i++) {
*(rvalues_[i]) = substitution;
}
Address substitution_entry = substitution->instruction_start();
for (int i = 0; i < reloc_infos_.length(); i++) {
reloc_infos_[i].set_target_address(substitution->instruction_start());
reloc_infos_[i].set_target_address(substitution_entry);
}
for (int i = 0; i < code_entries_.length(); i++) {
Address entry = code_entries_[i];
Memory::Address_at(entry) = substitution_entry;
}
}
@ -787,6 +798,7 @@ class ReferenceCollectorVisitor : public ObjectVisitor {
Code* original_;
ZoneList<Object**> rvalues_;
ZoneList<RelocInfo> reloc_infos_;
ZoneList<Address> code_entries_;
};

View File

@ -255,10 +255,9 @@ class StaticMarkingVisitor : public StaticVisitorBase {
static void EnableCodeFlushing(bool enabled) {
if (enabled) {
table_.Register(kVisitJSFunction, &VisitJSFunction);
table_.Register(kVisitJSFunction, &VisitJSFunctionAndFlushCode);
} else {
table_.Register(kVisitJSFunction,
&JSObjectVisitor::VisitSpecialized<JSFunction::kSize>);
table_.Register(kVisitJSFunction, &VisitJSFunction);
}
}
@ -299,7 +298,7 @@ class StaticMarkingVisitor : public StaticVisitorBase {
table_.Register(kVisitCode, &VisitCode);
table_.Register(kVisitJSFunction, &VisitJSFunction);
table_.Register(kVisitJSFunction, &VisitJSFunctionAndFlushCode);
table_.Register(kVisitPropertyCell,
&FixedBodyVisitor<StaticMarkingVisitor,
@ -534,17 +533,43 @@ class StaticMarkingVisitor : public StaticVisitorBase {
}
static void VisitJSFunction(Map* map, HeapObject* object) {
JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
static void VisitCodeEntry(Address entry_address) {
Object* code = Code::GetObjectFromEntryAddress(entry_address);
Object* old_code = code;
VisitPointer(&code);
if (code != old_code) {
Memory::Address_at(entry_address) =
reinterpret_cast<Code*>(code)->entry();
}
}
static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) {
JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
// The function must have a valid context and not be a builtin.
if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
FlushCodeForFunction(jsfunction);
}
JSObjectVisitor::VisitSpecialized<JSFunction::kSize>(map, object);
VisitJSFunction(map, object);
}
static void VisitJSFunction(Map* map, HeapObject* object) {
#define SLOT_ADDR(obj, offset) \
reinterpret_cast<Object**>((obj)->address() + offset)
VisitPointers(SLOT_ADDR(object, JSFunction::kPropertiesOffset),
SLOT_ADDR(object, JSFunction::kCodeEntryOffset));
VisitCodeEntry(object->address() + JSFunction::kCodeEntryOffset);
VisitPointers(SLOT_ADDR(object,
JSFunction::kCodeEntryOffset + kPointerSize),
SLOT_ADDR(object, JSFunction::kSize));
#undef SLOT_ADDR
}
typedef void (*Callback)(Map* map, HeapObject* object);
static VisitorDispatchTable<Callback> table_;

View File

@ -35,9 +35,10 @@
#ifndef V8_OBJECTS_INL_H_
#define V8_OBJECTS_INL_H_
#include "objects.h"
#include "memory.h"
#include "contexts.h"
#include "conversions-inl.h"
#include "objects.h"
#include "property.h"
namespace v8 {
@ -2410,6 +2411,12 @@ Code* Code::GetCodeFromTargetAddress(Address address) {
}
Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
return HeapObject::
FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
}
Object* Map::prototype() {
return READ_FIELD(this, kPrototypeOffset);
}
@ -2739,19 +2746,21 @@ bool JSFunction::IsBuiltin() {
Code* JSFunction::code() {
return Code::cast(READ_FIELD(this, kCodeOffset));
return Code::cast(unchecked_code());
}
Code* JSFunction::unchecked_code() {
return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
return reinterpret_cast<Code*>(
Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
}
void JSFunction::set_code(Code* value) {
// Skip the write barrier because code is never in new space.
ASSERT(!Heap::InNewSpace(value));
WRITE_FIELD(this, kCodeOffset, value);
Address entry = value->entry();
WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
}

View File

@ -1066,12 +1066,15 @@ void HeapObject::IterateBody(InstanceType type, int object_size,
case JS_VALUE_TYPE:
case JS_ARRAY_TYPE:
case JS_REGEXP_TYPE:
case JS_FUNCTION_TYPE:
case JS_GLOBAL_PROXY_TYPE:
case JS_GLOBAL_OBJECT_TYPE:
case JS_BUILTINS_OBJECT_TYPE:
JSObject::BodyDescriptor::IterateBody(this, object_size, v);
break;
case JS_FUNCTION_TYPE:
reinterpret_cast<JSFunction*>(this)
->JSFunctionIterateBody(object_size, v);
break;
case ODDBALL_TYPE:
Oddball::BodyDescriptor::IterateBody(this, v);
break;
@ -4988,6 +4991,15 @@ void Map::ClearNonLiveTransitions(Object* real_prototype) {
}
void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
// Iterate over all fields in the body but take care in dealing with
// the code entry.
IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
v->VisitCodeEntry(this->address() + kCodeEntryOffset);
IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
}
Object* JSFunction::SetInstancePrototype(Object* value) {
ASSERT(value->IsJSObject());
@ -5004,7 +5016,6 @@ Object* JSFunction::SetInstancePrototype(Object* value) {
}
Object* JSFunction::SetPrototype(Object* value) {
ASSERT(should_have_prototype());
Object* construct_prototype = value;
@ -5232,6 +5243,16 @@ void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
}
void ObjectVisitor::VisitCodeEntry(Address entry_address) {
Object* code = Code::GetObjectFromEntryAddress(entry_address);
Object* old_code = code;
VisitPointer(&code);
if (code != old_code) {
Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
}
}
void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
rinfo->IsPatchedReturnSequence()) ||

View File

@ -2883,6 +2883,9 @@ class Code: public HeapObject {
// Convert a target address into a code object.
static inline Code* GetCodeFromTargetAddress(Address address);
// Convert an entry address into an object.
static inline Object* GetObjectFromEntryAddress(Address location_of_address);
// Returns the address of the first instruction.
inline byte* instruction_start();
@ -3705,6 +3708,10 @@ class JSFunction: public JSObject {
// Casting.
static inline JSFunction* cast(Object* obj);
// Iterates the objects, including code objects indirectly referenced
// through pointers to the first instruction in the code object.
void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
// Dispatched behavior.
#ifdef DEBUG
void JSFunctionPrint();
@ -3718,9 +3725,9 @@ class JSFunction: public JSObject {
static Context* GlobalContextFromLiterals(FixedArray* literals);
// Layout descriptors.
static const int kCodeOffset = JSObject::kHeaderSize;
static const int kCodeEntryOffset = JSObject::kHeaderSize;
static const int kPrototypeOrInitialMapOffset =
kCodeOffset + kPointerSize;
kCodeEntryOffset + kPointerSize;
static const int kSharedFunctionInfoOffset =
kPrototypeOrInitialMapOffset + kPointerSize;
static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
@ -5435,6 +5442,9 @@ class ObjectVisitor BASE_EMBEDDED {
// Visits a code target in the instruction stream.
virtual void VisitCodeTarget(RelocInfo* rinfo);
// Visits a code entry in a JS function.
virtual void VisitCodeEntry(Address entry_address);
// Visits a runtime entry in the instruction stream.
virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}

View File

@ -831,6 +831,12 @@ void Deserializer::ReadChunk(Object** current,
CASE_STATEMENT(where, how, within, kLargeFixedArray) \
CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)
#define ONE_PER_CODE_SPACE(where, how, within) \
CASE_STATEMENT(where, how, within, CODE_SPACE) \
CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \
CASE_STATEMENT(where, how, within, kLargeCode) \
CASE_BODY(where, how, within, LO_SPACE, kUnknownOffsetFromStart)
#define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number, \
space_number, \
offset_from_start) \
@ -862,6 +868,8 @@ void Deserializer::ReadChunk(Object** current,
// Deserialize a new object and write a pointer to it to the current
// object.
ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject)
// Support for direct instruction pointers in functions
ONE_PER_CODE_SPACE(kNewObject, kPlain, kFirstInstruction)
// Deserialize a new code object and write a pointer to its first
// instruction to the current code object.
ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction)
@ -870,11 +878,14 @@ void Deserializer::ReadChunk(Object** current,
ALL_SPACES(kBackref, kPlain, kStartOfObject)
// Find a recently deserialized code object using its offset from the
// current allocation point and write a pointer to its first instruction
// to the current code object.
// to the current code object or the instruction pointer in a function
// object.
ALL_SPACES(kBackref, kFromCode, kFirstInstruction)
ALL_SPACES(kBackref, kPlain, kFirstInstruction)
// Find an already deserialized object using its offset from the start
// and write a pointer to it to the current object.
ALL_SPACES(kFromStart, kPlain, kStartOfObject)
ALL_SPACES(kFromStart, kPlain, kFirstInstruction)
// Find an already deserialized code object using its offset from the
// start and write a pointer to its first instruction to the current code
// object.
@ -894,6 +905,14 @@ void Deserializer::ReadChunk(Object** current,
kStartOfObject,
0,
kUnknownOffsetFromStart)
// Find an code entry in the partial snapshots cache and
// write a pointer to it to the current object.
CASE_STATEMENT(kPartialSnapshotCache, kPlain, kFirstInstruction, 0)
CASE_BODY(kPartialSnapshotCache,
kPlain,
kFirstInstruction,
0,
kUnknownOffsetFromStart)
// Find an external reference and write a pointer to it to the current
// object.
CASE_STATEMENT(kExternalReference, kPlain, kStartOfObject, 0)
@ -1336,6 +1355,14 @@ void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
}
void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
OutputRawData(entry_address);
serializer_->SerializeObject(target, kPlain, kFirstInstruction);
bytes_processed_so_far_ += kPointerSize;
}
void Serializer::ObjectSerializer::VisitExternalAsciiString(
v8::String::ExternalAsciiStringResource** resource_pointer) {
Address references_start = reinterpret_cast<Address>(resource_pointer);

View File

@ -448,6 +448,7 @@ class Serializer : public SerializerDeserializer {
void VisitPointers(Object** start, Object** end);
void VisitExternalReferences(Address* start, Address* end);
void VisitCodeTarget(RelocInfo* target);
void VisitCodeEntry(Address entry_address);
void VisitRuntimeEntry(RelocInfo* reloc);
// Used for seralizing the external strings that hold the natives source.
void VisitExternalAsciiString(

View File

@ -310,8 +310,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ movsxlq(rbx,
FieldOperand(rdx,
SharedFunctionInfo::kFormalParameterCountOffset));
__ movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
__ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
__ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
__ cmpq(rax, rbx);
__ j(not_equal,
Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),

View File

@ -2616,8 +2616,10 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
__ j(is_smi, &build_args);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rcx);
__ j(not_equal, &build_args);
__ movq(rcx, FieldOperand(rax, JSFunction::kCodeEntryOffset));
__ subq(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag));
Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
__ Cmp(FieldOperand(rax, JSFunction::kCodeOffset), apply_code);
__ Cmp(FieldOperand(rcx, SharedFunctionInfo::kCodeOffset), apply_code);
__ j(not_equal, &build_args);
// Check that applicand is a function.
@ -8758,7 +8760,8 @@ void FastNewClosureStub::Generate(MacroAssembler* masm) {
// 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);
__ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
__ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);
// Return and remove the on-stack parameter.

View File

@ -581,28 +581,21 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
ASSERT(!target.is(rdi));
void MacroAssembler::GetBuiltinFunction(Register target,
Builtins::JavaScript id) {
// Load the builtins object into target register.
movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
movq(target, FieldOperand(target,
JSBuiltinsObject::OffsetOfFunctionWithId(id)));
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
ASSERT(!target.is(rdi));
// Load the JavaScript builtin function from the builtins object.
movq(rdi, FieldOperand(target, JSBuiltinsObject::OffsetOfFunctionWithId(id)));
// Load the code entry point from the builtins object.
movq(target, FieldOperand(target, JSBuiltinsObject::OffsetOfCodeWithId(id)));
if (FLAG_debug_code) {
// Make sure the code objects in the builtins object and in the
// builtin function are the same.
push(target);
movq(target, FieldOperand(rdi, JSFunction::kCodeOffset));
cmpq(target, Operand(rsp, 0));
Assert(equal, "Builtin code object changed");
pop(target);
}
lea(target, FieldOperand(target, Code::kHeaderSize));
GetBuiltinFunction(rdi, id);
movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
}
@ -2311,10 +2304,9 @@ void MacroAssembler::InvokeFunction(Register function,
movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
movsxlq(rbx,
FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
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));
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
ParameterCount expected(rbx);
InvokeCode(rdx, expected, actual, flag);

View File

@ -203,6 +203,9 @@ class MacroAssembler: public Assembler {
// the unresolved list if the name does not resolve.
void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);
// Store the function for the given builtin in the target register.
void GetBuiltinFunction(Register target, Builtins::JavaScript id);
// Store the code object for the given builtin in the target register.
void GetBuiltinEntry(Register target, Builtins::JavaScript id);