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
-~----------~----~----~----~------~----~------~--~---

Reply via email to