Author: [EMAIL PROTECTED]
Date: Fri Oct 10 02:09:38 2008
New Revision: 485
Modified:
branches/bleeding_edge/src/builtins-arm.cc
branches/bleeding_edge/src/builtins-ia32.cc
branches/bleeding_edge/src/builtins.cc
branches/bleeding_edge/src/builtins.h
branches/bleeding_edge/src/frames-inl.h
branches/bleeding_edge/src/frames.cc
branches/bleeding_edge/src/frames.h
branches/bleeding_edge/src/macro-assembler-arm.cc
branches/bleeding_edge/src/macro-assembler-arm.h
branches/bleeding_edge/src/macro-assembler-ia32.cc
branches/bleeding_edge/src/macro-assembler-ia32.h
branches/bleeding_edge/src/runtime.cc
Log:
Introduce a special kind of frames for construct frames, e.g.
the trampoline frames introduced for invoking functions through
the new keyword.
Review URL: http://codereview.chromium.org/7223
Modified: branches/bleeding_edge/src/builtins-arm.cc
==============================================================================
--- branches/bleeding_edge/src/builtins-arm.cc (original)
+++ branches/bleeding_edge/src/builtins-arm.cc Fri Oct 10 02:09:38 2008
@@ -58,8 +58,8 @@
// -- sp[...]: constructor arguments
// -----------------------------------
- // Enter an internal frame.
- __ EnterInternalFrame();
+ // Enter a construct frame.
+ __ EnterConstructFrame();
// Preserve the two incoming parameters
__ mov(r0, Operand(r0, LSL, kSmiTagSize));
@@ -116,10 +116,8 @@
// Call the function.
// r0: number of arguments
// r1: constructor function
- Label return_site;
ParameterCount actual(r0);
__ InvokeFunction(r1, actual, CALL_FUNCTION);
- __ bind(&return_site);
// Pop the function from the stack.
// sp[0]: constructor function
@@ -168,15 +166,10 @@
// sp[1]: constructor function
// sp[2]: number of arguments (smi-tagged)
__ ldr(r1, MemOperand(sp, 2 * kPointerSize));
- __ LeaveInternalFrame();
+ __ LeaveConstructFrame();
__ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
__ add(sp, sp, Operand(kPointerSize));
__ mov(pc, Operand(lr));
-
- // Compute the offset from the beginning of the JSConstructCall
- // builtin code object to the return address after the call.
- ASSERT(return_site.is_bound());
- construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;
}
@@ -539,7 +532,7 @@
}
-static void ExitArgumentsAdaptorFrame(MacroAssembler* masm) {
+static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : result being passed through
// -----------------------------------
@@ -641,19 +634,12 @@
}
// Call the entry point.
- Label return_site;
__ bind(&invoke);
-
__ Call(r3);
- __ bind(&return_site);
- ExitArgumentsAdaptorFrame(masm);
+ // Exit frame and return.
+ LeaveArgumentsAdaptorFrame(masm);
__ mov(pc, lr);
-
- // Compute the offset from the beginning of the
ArgumentsAdaptorTrampoline
- // builtin code object to the return address after the call.
- ASSERT(return_site.is_bound());
- arguments_adaptor_call_pc_offset_ = return_site.pos() +
Code::kHeaderSize;
// -------------------------------------------
Modified: branches/bleeding_edge/src/builtins-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/builtins-ia32.cc (original)
+++ branches/bleeding_edge/src/builtins-ia32.cc Fri Oct 10 02:09:38 2008
@@ -56,8 +56,8 @@
// -- edi: constructor function
// -----------------------------------
- // Enter an internal frame.
- __ EnterInternalFrame();
+ // Enter a construct frame.
+ __ EnterConstructFrame();
// Store a smi-tagged arguments count on the stack.
__ shl(eax, kSmiTagSize);
@@ -265,10 +265,8 @@
__ j(greater_equal, &loop);
// Call the function.
- Label return_site;
ParameterCount actual(eax);
__ InvokeFunction(edi, actual, CALL_FUNCTION);
- __ bind(&return_site);
// Restore context from the frame.
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
@@ -294,10 +292,10 @@
__ bind(&use_receiver);
__ mov(eax, Operand(esp, 0));
- // Restore the arguments count and exit the internal frame.
+ // Restore the arguments count and leave the construct frame.
__ bind(&exit);
__ mov(ebx, Operand(esp, kPointerSize)); // get arguments count
- __ LeaveInternalFrame();
+ __ LeaveConstructFrame();
// Remove caller arguments from the stack and return.
ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
@@ -305,11 +303,6 @@
__ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~
receiver
__ push(ecx);
__ ret(0);
-
- // Compute the offset from the beginning of the JSConstructCall
- // builtin code object to the return address after the call.
- ASSERT(return_site.is_bound());
- construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;
}
@@ -662,7 +655,7 @@
}
-static void ExitArgumentsAdaptorFrame(MacroAssembler* masm) {
+static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
// Retrieve the number of arguments from the stack.
__ mov(ebx, Operand(ebp, ArgumentsAdaptorFrameConstants::kLengthOffset));
@@ -742,19 +735,12 @@
}
// Call the entry point.
- Label return_site;
__ bind(&invoke);
__ call(Operand(edx));
- __ bind(&return_site);
- ExitArgumentsAdaptorFrame(masm);
+ // Leave frame and return.
+ LeaveArgumentsAdaptorFrame(masm);
__ ret(0);
-
- // Compute the offset from the beginning of the
ArgumentsAdaptorTrampoline
- // builtin code object to the return address after the call.
- ASSERT(return_site.is_bound());
- arguments_adaptor_call_pc_offset_ = return_site.pos() +
Code::kHeaderSize;
-
// -------------------------------------------
// Dont adapt arguments.
Modified: branches/bleeding_edge/src/builtins.cc
==============================================================================
--- branches/bleeding_edge/src/builtins.cc (original)
+++ branches/bleeding_edge/src/builtins.cc Fri Oct 10 02:09:38 2008
@@ -94,31 +94,11 @@
ASSERT(it.frame()->is_exit());
it.Advance();
StackFrame* frame = it.frame();
- return frame->is_internal() &&
- InternalFrame::cast(frame)->is_construct_trampoline();
+ return frame->is_construct();
}
//
----------------------------------------------------------------------------
-
-
-int Builtins::construct_call_pc_offset_ = 0;
-int Builtins::arguments_adaptor_call_pc_offset_ = 0;
-
-
-// Check if the builtin was called in a 'new' call.
-bool Builtins::IsConstructCall(Address pc) {
- ASSERT(construct_call_pc_offset_ > 0);
- int offset = pc - builtin(JSConstructCall)->address();
- return offset == construct_call_pc_offset_;
-}
-
-
-bool Builtins::IsArgumentsAdaptorCall(Address pc) {
- ASSERT(arguments_adaptor_call_pc_offset_ > 0);
- int offset = pc - builtin(ArgumentsAdaptorTrampoline)->address();
- return offset == arguments_adaptor_call_pc_offset_;
-}
Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
Modified: branches/bleeding_edge/src/builtins.h
==============================================================================
--- branches/bleeding_edge/src/builtins.h (original)
+++ branches/bleeding_edge/src/builtins.h Fri Oct 10 02:09:38 2008
@@ -167,9 +167,6 @@
id_count
};
- static bool IsConstructCall(Address pc);
- static bool IsArgumentsAdaptorCall(Address pc);
-
static Code* builtin(Name name) {
// Code::cast cannot be used here since we access builtins
// during the marking phase of mark sweep. See IC::Clear.
@@ -205,12 +202,6 @@
static const char* names_[builtin_count];
static const char* javascript_names_[id_count];
static int javascript_argc_[id_count];
-
- // The offset from the beginning of the JSConstructCall builtin code
- // object to the return address after the call. Used for determining
- // if a call is a constructor invocation.
- static int construct_call_pc_offset_;
- static int arguments_adaptor_call_pc_offset_;
static void Generate_Adaptor(MacroAssembler* masm, CFunctionId id);
static void Generate_JSConstructCall(MacroAssembler* masm);
Modified: branches/bleeding_edge/src/frames-inl.h
==============================================================================
--- branches/bleeding_edge/src/frames-inl.h (original)
+++ branches/bleeding_edge/src/frames-inl.h Fri Oct 10 02:09:38 2008
@@ -145,8 +145,10 @@
}
-inline bool StandardFrame::IsConstructTrampolineFrame(Address pc) {
- return Builtins::builtin(Builtins::JSConstructCall)->contains(pc);
+inline bool StandardFrame::IsConstructFrame(Address fp) {
+ Object* marker =
+ Memory::Object_at(fp + StandardFrameConstants::kMarkerOffset);
+ return marker == Smi::FromInt(CONSTRUCT);
}
@@ -164,15 +166,6 @@
inline bool JavaScriptFrame::has_adapted_arguments() const {
return IsArgumentsAdaptorFrame(caller_fp());
-}
-
-
-inline bool InternalFrame::is_construct_trampoline() const {
- // TODO(1233795): This doesn't work when the stack frames have been
- // cooked. We need to find another way of identifying construct
- // trampoline frames possibly by manipulating the context field like
- // we do for argument adaptor frames.
- return IsConstructTrampolineFrame(pc());
}
Modified: branches/bleeding_edge/src/frames.cc
==============================================================================
--- branches/bleeding_edge/src/frames.cc (original)
+++ branches/bleeding_edge/src/frames.cc Fri Oct 10 02:09:38 2008
@@ -311,10 +311,12 @@
bool JavaScriptFrame::IsConstructor() const {
- Address pc = has_adapted_arguments()
- ? Memory::Address_at(ComputePCAddress(caller_fp()))
- : caller_pc();
- return IsConstructTrampolineFrame(pc);
+ Address fp = caller_fp();
+ if (has_adapted_arguments()) {
+ // Skip the arguments adaptor frame and look at the real caller.
+ fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
+ }
+ return IsConstructFrame(fp);
}
Modified: branches/bleeding_edge/src/frames.h
==============================================================================
--- branches/bleeding_edge/src/frames.h (original)
+++ branches/bleeding_edge/src/frames.h Fri Oct 10 02:09:38 2008
@@ -98,6 +98,7 @@
V(EXIT_DEBUG, ExitDebugFrame) \
V(JAVA_SCRIPT, JavaScriptFrame) \
V(INTERNAL, InternalFrame) \
+ V(CONSTRUCT, ConstructFrame) \
V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
@@ -124,6 +125,7 @@
bool is_java_script() const { return type() == JAVA_SCRIPT; }
bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
bool is_internal() const { return type() == INTERNAL; }
+ bool is_construct() const { return type() == CONSTRUCT; }
virtual bool is_standard() const { return false; }
// Accessors.
@@ -352,9 +354,9 @@
// an arguments adaptor frame.
static inline bool IsArgumentsAdaptorFrame(Address fp);
- // Determines if the standard frame for the given program counter is
- // a construct trampoline.
- static inline bool IsConstructTrampolineFrame(Address pc);
+ // Determines if the standard frame for the given frame pointer is a
+ // construct frame.
+ static inline bool IsConstructFrame(Address fp);
private:
friend class StackFrame;
@@ -380,9 +382,7 @@
// computed parameters count.
int GetProvidedParametersCount() const;
- // Check if this frame is a constructor frame invoked through
- // 'new'. The operation may involve digging through a few stack
- // frames to account for arguments adaptors.
+ // Check if this frame is a constructor frame invoked through 'new'.
bool IsConstructor() const;
// Check if this frame has "adapted" arguments in the sense that the
@@ -459,11 +459,6 @@
public:
virtual Type type() const { return INTERNAL; }
- // Returns if this frame is a special trampoline frame introduced by
- // the construct trampoline. NOTE: We should consider introducing a
- // special stack frame type for this.
- inline bool is_construct_trampoline() const;
-
// Garbage colletion support.
virtual void Iterate(ObjectVisitor* v) const;
@@ -480,6 +475,26 @@
: StandardFrame(iterator) { }
virtual Address GetCallerStackPointer() const;
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
+// Construct frames are special trampoline frames introduced to handle
+// function invocations through 'new'.
+class ConstructFrame: public InternalFrame {
+ public:
+ virtual Type type() const { return CONSTRUCT; }
+
+ static ConstructFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_construct());
+ return static_cast<ConstructFrame*>(frame);
+ }
+
+ protected:
+ explicit ConstructFrame(StackFrameIterator* iterator)
+ : InternalFrame(iterator) { }
private:
friend class StackFrameIterator;
Modified: branches/bleeding_edge/src/macro-assembler-arm.cc
==============================================================================
--- branches/bleeding_edge/src/macro-assembler-arm.cc (original)
+++ branches/bleeding_edge/src/macro-assembler-arm.cc Fri Oct 10 02:09:38
2008
@@ -251,10 +251,8 @@
}
-void MacroAssembler::EnterInternalFrame() {
+void MacroAssembler::EnterFrame(StackFrame::Type type) {
// r0-r3: preserved
- int type = StackFrame::INTERNAL;
-
stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
mov(ip, Operand(Smi::FromInt(type)));
push(ip);
@@ -264,13 +262,13 @@
}
-void MacroAssembler::LeaveInternalFrame() {
+void MacroAssembler::LeaveFrame(StackFrame::Type type) {
// r0: preserved
// r1: preserved
// r2: preserved
- // Drop the execution stack down to the frame pointer and restore the
caller
- // frame pointer and return address.
+ // Drop the execution stack down to the frame pointer and restore
+ // the caller frame pointer and return address.
mov(sp, fp);
ldm(ia_w, sp, fp.bit() | lr.bit());
}
Modified: branches/bleeding_edge/src/macro-assembler-arm.h
==============================================================================
--- branches/bleeding_edge/src/macro-assembler-arm.h (original)
+++ branches/bleeding_edge/src/macro-assembler-arm.h Fri Oct 10 02:09:38
2008
@@ -99,8 +99,11 @@
//
---------------------------------------------------------------------------
// Activation frames
- void EnterInternalFrame();
- void LeaveInternalFrame();
+ void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
+ void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
+
+ void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+ void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
// Enter specific kind of exit frame; either EXIT or
// EXIT_DEBUG. Expects the number of arguments in register r0 and
@@ -260,6 +263,10 @@
// Get the code for the given builtin. Returns if able to resolve
// the function in the 'resolved' flag.
Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
+
+ // Activation support.
+ void EnterFrame(StackFrame::Type type);
+ void LeaveFrame(StackFrame::Type type);
};
Modified: branches/bleeding_edge/src/macro-assembler-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/macro-assembler-ia32.cc (original)
+++ branches/bleeding_edge/src/macro-assembler-ia32.cc Fri Oct 10 02:09:38
2008
@@ -312,9 +312,7 @@
}
-void MacroAssembler::EnterInternalFrame() {
- int type = StackFrame::INTERNAL;
-
+void MacroAssembler::EnterFrame(StackFrame::Type type) {
push(ebp);
mov(ebp, Operand(esp));
push(esi);
@@ -323,9 +321,8 @@
}
-void MacroAssembler::LeaveInternalFrame() {
+void MacroAssembler::LeaveFrame(StackFrame::Type type) {
if (FLAG_debug_code) {
- StackFrame::Type type = StackFrame::INTERNAL;
cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
Immediate(Smi::FromInt(type)));
Check(equal, "stack frame types must match");
Modified: branches/bleeding_edge/src/macro-assembler-ia32.h
==============================================================================
--- branches/bleeding_edge/src/macro-assembler-ia32.h (original)
+++ branches/bleeding_edge/src/macro-assembler-ia32.h Fri Oct 10 02:09:38
2008
@@ -86,8 +86,11 @@
//
---------------------------------------------------------------------------
// Activation frames
- void EnterInternalFrame();
- void LeaveInternalFrame();
+ void EnterInternalFrame() { EnterFrame(StackFrame::INTERNAL); }
+ void LeaveInternalFrame() { LeaveFrame(StackFrame::INTERNAL); }
+
+ void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
+ void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
// Enter specific kind of exit frame; either EXIT or
// EXIT_DEBUG. Expects the number of arguments in register eax and
@@ -274,6 +277,10 @@
// Get the code for the given builtin. Returns if able to resolve
// the function in the 'resolved' flag.
Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
+
+ // Activation support.
+ void EnterFrame(StackFrame::Type type);
+ void LeaveFrame(StackFrame::Type type);
};
Modified: branches/bleeding_edge/src/runtime.cc
==============================================================================
--- branches/bleeding_edge/src/runtime.cc (original)
+++ branches/bleeding_edge/src/runtime.cc Fri Oct 10 02:09:38 2008
@@ -2917,7 +2917,7 @@
if (Debug::StepInActive()) {
StackFrameIterator it;
it.Advance();
- ASSERT(InternalFrame::cast(it.frame())->is_construct_trampoline());
+ ASSERT(it.frame()->is_construct());
it.Advance();
if (it.frame()->fp() == Debug::step_in_fp()) {
HandleScope scope;
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---