Author: [EMAIL PROTECTED]
Date: Fri Nov 14 04:47:25 2008
New Revision: 756

Modified:
    branches/experimental/toiger/SConstruct
    branches/experimental/toiger/include/v8.h
    branches/experimental/toiger/src/api.cc
    branches/experimental/toiger/src/codegen-arm.cc
    branches/experimental/toiger/src/codegen-ia32.cc
    branches/experimental/toiger/src/ic-arm.cc
    branches/experimental/toiger/src/simulator-arm.cc
    branches/experimental/toiger/src/simulator-arm.h
    branches/experimental/toiger/src/stub-cache-arm.cc
    branches/experimental/toiger/src/top.cc
    branches/experimental/toiger/test/cctest/cctest.status
    branches/experimental/toiger/tools/visual_studio/arm.vsprops

Log:
Experimental: periodic merge to the experimental branch from
bleeding_edge.  Merge bleeding [EMAIL PROTECTED]
Review URL: http://codereview.chromium.org/10945

Modified: branches/experimental/toiger/SConstruct
==============================================================================
--- branches/experimental/toiger/SConstruct     (original)
+++ branches/experimental/toiger/SConstruct     Fri Nov 14 04:47:25 2008
@@ -106,7 +106,10 @@
        'CPPDEFINES':   ['BUILDING_V8_SHARED']
      },
      'arch:arm': {
-      'CPPDEFINES':   ['ARM']
+      'CPPDEFINES':   ['ARM'],
+      # /wd4996 is to silence the warning about sscanf
+      # used by the arm simulator.
+      'WARNINGFLAGS': ['/wd4996']
      },
      'disassembler:on': {
        'CPPDEFINES':   ['ENABLE_DISASSEMBLER']

Modified: branches/experimental/toiger/include/v8.h
==============================================================================
--- branches/experimental/toiger/include/v8.h   (original)
+++ branches/experimental/toiger/include/v8.h   Fri Nov 14 04:47:25 2008
@@ -2052,6 +2052,7 @@
    void* message_;
    bool is_verbose_;
    bool capture_message_;
+  void* js_handler_;
  };



Modified: branches/experimental/toiger/src/api.cc
==============================================================================
--- branches/experimental/toiger/src/api.cc     (original)
+++ branches/experimental/toiger/src/api.cc     Fri Nov 14 04:47:25 2008
@@ -1081,7 +1081,8 @@
        exception_(i::Heap::the_hole_value()),
        message_(i::Smi::FromInt(0)),
        is_verbose_(false),
-      capture_message_(true) {
+      capture_message_(true),
+      js_handler_(NULL) {
    i::Top::RegisterTryCatchHandler(this);
  }


Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc     (original)
+++ branches/experimental/toiger/src/codegen-arm.cc     Fri Nov 14 04:47:25 2008
@@ -3128,56 +3128,47 @@
    Expression* right = node->right();
    Token::Value op = node->op();

-  // NOTE: To make null checks efficient, we check if either left or
-  // right is the literal 'null'. If so, we optimize the code by
-  // inlining a null check instead of calling the (very) general
-  // runtime routine for checking equality.
-
+  // To make null checks efficient, we check if either left or right is the
+  // literal 'null'. If so, we optimize the code by inlining a null check
+  // instead of calling the (very) general runtime routine for checking
+  // equality.
    if (op == Token::EQ || op == Token::EQ_STRICT) {
      bool left_is_null =
-      left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+        left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
      bool right_is_null =
-      right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
-    // The 'null' value is only equal to 'null' or 'undefined'.
+        right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+    // The 'null' value can only be equal to 'null' or 'undefined'.
      if (left_is_null || right_is_null) {
        Load(left_is_null ? right : left);
-      JumpTarget exit(this);
-      JumpTarget undetectable(this);
        frame_->Pop(r0);
        __ cmp(r0, Operand(Factory::null_value()));

-      // The 'null' value is only equal to 'undefined' if using
-      // non-strict comparisons.
+      // The 'null' value is only equal to 'undefined' if using non-strict
+      // comparisons.
        if (op != Token::EQ_STRICT) {
-        exit.Branch(eq);
+        true_target()->Branch(eq);
+
          __ cmp(r0, Operand(Factory::undefined_value()));
+        true_target()->Branch(eq);

-        // NOTE: it can be undetectable object.
-        exit.Branch(eq);
          __ tst(r0, Operand(kSmiTagMask));
+        false_target()->Branch(eq);

-        undetectable.Branch(ne);
-        false_target()->Jump();
-
-        undetectable.Bind();
-        __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-        __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
-        __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
-        __ cmp(r2, Operand(1 << Map::kIsUndetectable));
+        // It can be an undetectable object.
+        __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+        __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset));
+        __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
+        __ cmp(r0, Operand(1 << Map::kIsUndetectable));
        }

-      exit.Bind();
-
        cc_reg_ = eq;
        return;
      }
    }

-
-  // NOTE: To make typeof testing for natives implemented in
-  // JavaScript really efficient, we generate special code for
-  // expressions of the form: 'typeof <expression> == <string>'.
-
+  // To make typeof testing for natives implemented in JavaScript really
+  // efficient, we generate special code for expressions of the form:
+  // 'typeof <expression> == <string>'.
    UnaryOperation* operation = left->AsUnaryOperation();
    if ((op == Token::EQ || op == Token::EQ_STRICT) &&
        (operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -3202,7 +3193,7 @@

        __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));

-      // NOTE: it might be an undetectable string object
+      // It can be an undetectable string object.
        __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
        __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
        __ cmp(r2, Operand(1 << Map::kIsUndetectable));
@@ -3225,7 +3216,7 @@
        __ tst(r1, Operand(kSmiTagMask));
        false_target()->Branch(eq);

-      // NOTE: it can be undetectable object.
+      // It can be an undetectable object.
        __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
        __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
        __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
@@ -3249,7 +3240,7 @@
        __ cmp(r1, Operand(Factory::null_value()));
        true_target()->Branch(eq);

-      // NOTE: it might be an undetectable object.
+      // It can be an undetectable object.
        __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
        __ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
        __ cmp(r1, Operand(1 << Map::kIsUndetectable));
@@ -3262,8 +3253,8 @@
        cc_reg_ = le;

      } else {
-      // Uncommon case: Typeof testing against a string literal that
-      // is never returned from the typeof operator.
+      // Uncommon case: typeof testing against a string literal that is
+      // never returned from the typeof operator.
        false_target()->Jump();
      }
      return;
@@ -3391,9 +3382,15 @@
        // distinction between expressions in a typeof and not in a typeof.
        Comment cmnt(masm, "[ Load from keyed Property");
        ASSERT(property != NULL);
-      // TODO(1224671): Implement inline caching for keyed loads as on  
ia32.
-      GetPropertyStub stub;
-      frame->CallStub(&stub, 0);
+      Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+
+      Variable* var = expression_->AsVariableProxy()->AsVariable();
+      if (var != NULL) {
+        ASSERT(var->is_global());
+        frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
+      } else {
+        frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+      }
        frame->Push(r0);
        break;
      }
@@ -3500,11 +3497,11 @@
      case NAMED: {
        Comment cmnt(masm, "[ Store to named Property");
        // Call the appropriate IC code.
+      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
        frame->Pop(r0);  // value
        // Setup the name register.
        Handle<String> name(GetName());
        __ mov(r2, Operand(name));
-      Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
        frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
        frame->Push(r0);
        break;
@@ -3515,9 +3512,12 @@
        Property* property = expression_->AsProperty();
        ASSERT(property != NULL);
        __ RecordPosition(property->position());
+
+      // Call IC code.
+      Handle<Code>  
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+      // TODO(1222589): Make the IC grab the values from the stack.
        frame->Pop(r0);  // value
-      SetPropertyStub stub;
-      frame->CallStub(&stub, 0);
+      frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
        frame->Push(r0);
        break;
      }

Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc    (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc    Fri Nov 14 04:47:25  
2008
@@ -3692,55 +3692,47 @@
    Expression* right = node->right();
    Token::Value op = node->op();

-  // NOTE: To make null checks efficient, we check if either left or
-  // right is the literal 'null'. If so, we optimize the code by
-  // inlining a null check instead of calling the (very) general
-  // runtime routine for checking equality.
-
+  // To make null checks efficient, we check if either left or right is the
+  // literal 'null'. If so, we optimize the code by inlining a null check
+  // instead of calling the (very) general runtime routine for checking
+  // equality.
    if (op == Token::EQ || op == Token::EQ_STRICT) {
      bool left_is_null =
-      left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+        left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
      bool right_is_null =
-      right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
-    // The 'null' value is only equal to 'null' or 'undefined'.
+        right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+    // The 'null' value can only be equal to 'null' or 'undefined'.
      if (left_is_null || right_is_null) {
        Load(left_is_null ? right : left);
-      JumpTarget exit(this);
-      JumpTarget undetectable(this);
        frame_->Pop(eax);
        __ cmp(eax, Factory::null_value());

-      // The 'null' value is only equal to 'undefined' if using
-      // non-strict comparisons.
+      // The 'null' value is only equal to 'undefined' if using non-strict
+      // comparisons.
        if (op != Token::EQ_STRICT) {
-        exit.Branch(equal);
+        true_target()->Branch(equal);
+
          __ cmp(eax, Factory::undefined_value());
+        true_target()->Branch(equal);

-        // NOTE: it can be an undetectable object.
-        exit.Branch(equal);
          __ test(eax, Immediate(kSmiTagMask));
+        false_target()->Branch(equal);

-        undetectable.Branch(not_equal);
-        false_target()->Jump();
-
-        undetectable.Bind();
-        __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-        __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
-        __ and_(ecx, 1 << Map::kIsUndetectable);
-        __ cmp(ecx, 1 << Map::kIsUndetectable);
+        // It can be an undetectable object.
+        __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
+        __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
+        __ and_(eax, 1 << Map::kIsUndetectable);
+        __ cmp(eax, 1 << Map::kIsUndetectable);
        }

-      exit.Bind();
-
        cc_reg_ = equal;
        return;
      }
    }

-  // NOTE: To make typeof testing for natives implemented in
-  // JavaScript really efficient, we generate special code for
-  // expressions of the form: 'typeof <expression> == <string>'.
-
+  // To make typeof testing for natives implemented in JavaScript really
+  // efficient, we generate special code for expressions of the form:
+  // 'typeof <expression> == <string>'.
    UnaryOperation* operation = left->AsUnaryOperation();
    if ((op == Token::EQ || op == Token::EQ_STRICT) &&
        (operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -3748,7 +3740,7 @@
         right->AsLiteral()->handle()->IsString())) {
      Handle<String> check(String::cast(*right->AsLiteral()->handle()));

-    // Load the operand, move it to register edx, and restore TOS.
+    // Load the operand and move it to register edx.
      LoadTypeofExpression(operation->expression());
      frame_->Pop(edx);

@@ -3765,7 +3757,7 @@

        __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));

-      // NOTE: it might be an undetectable string object
+      // It can be an undetectable string object.
        __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
        __ and_(ecx, 1 << Map::kIsUndetectable);
        __ cmp(ecx, 1 << Map::kIsUndetectable);
@@ -3788,7 +3780,7 @@
        __ test(edx, Immediate(kSmiTagMask));
        false_target()->Branch(zero);

-      // NOTE: it can be an undetectable object.
+      // It can be an undetectable object.
        __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
        __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
        __ and_(ecx, 1 << Map::kIsUndetectable);
@@ -3812,7 +3804,7 @@
        __ cmp(edx, Factory::null_value());
        true_target()->Branch(equal);

-      // NOTE: it might be an undetectable object
+      // It can be an undetectable object.
        __ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset));
        __ and_(edx, 1 << Map::kIsUndetectable);
        __ cmp(edx, 1 << Map::kIsUndetectable);
@@ -3825,8 +3817,8 @@
        cc_reg_ = less_equal;

      } else {
-      // Uncommon case: Typeof testing against a string literal that
-      // is never returned from the typeof operator.
+      // Uncommon case: typeof testing against a string literal that is
+      // never returned from the typeof operator.
        false_target()->Jump();
        // TODO(): Can this cause a problem because it is an expression that
        // exits without a virtual frame in place?

Modified: branches/experimental/toiger/src/ic-arm.cc
==============================================================================
--- branches/experimental/toiger/src/ic-arm.cc  (original)
+++ branches/experimental/toiger/src/ic-arm.cc  Fri Nov 14 04:47:25 2008
@@ -136,24 +136,9 @@

    __ ldr(r0, MemOperand(sp, 0));

-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the object is a JS array.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-  __ cmp(r1, Operand(JS_ARRAY_TYPE));
-  __ b(ne, &miss);
-
-  // Load length directly from the JS array.
-  __ ldr(r0, FieldMemOperand(r0, JSArray::kLengthOffset));
-  __ Ret();
-
-  // Cache miss: Jump to runtime.
+  StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
    __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
  }


@@ -185,7 +170,6 @@
    //  -- lr    : return address
    //  -- [sp]  : receiver
    // -----------------------------------
-
    Label miss, load_length, check_wrapper;

    __ ldr(r0, MemOperand(sp, 0));
@@ -216,8 +200,7 @@

    // Cache miss: Jump to runtime.
    __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
  }


@@ -509,33 +492,87 @@
    //  -- [sp]  : receiver
    // -----------------------------------

-  __ ldr(r0, MemOperand(sp, 0));
-  __ push(r0);
-  __ push(r2);
+  __ ldr(r3, MemOperand(sp, 0));
+  __ stm(db_w, sp, r2.bit() | r3.bit());

    // Perform tail call to the entry.
    __ TailCallRuntime(f, 2);
  }


-// TODO(1224671): ICs for keyed load/store is not implemented on ARM.
+// TODO(1224671): ICs for keyed load/store is not completed on ARM.
+Object* KeyedLoadIC_Miss(Arguments args);
+
+
  void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
+  Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
  }

+
  void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference&  
f) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[4]  : receiver
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r2.bit() | r3.bit());
+
+  __ TailCallRuntime(f, 2);
  }

+
+// TODO(1224671): implement the fast case.
  void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[4]  : receiver
+
+  KeyedLoadIC::Generate(masm,  
ExternalReference(Runtime::kKeyedGetProperty));
  }

+
  void KeyedStoreIC::Generate(MacroAssembler* masm,
                              const ExternalReference& f) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  __ TailCallRuntime(f, 3);
  }

+
+// TODO(1224671): implement the fast case.
  void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+
+  KeyedStoreIC::Generate(masm, ExternalReference(Runtime::kSetProperty));
  }

+
  void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+  // ---------- S t a t e --------------
+  //  -- r0     : value
+  //  -- lr     : return address
+  //  -- sp[0]  : key
+  //  -- sp[1]  : receiver
+  // ----------- S t a t e -------------
+
+  __ ldm(ia, sp, r2.bit() | r3.bit());
+  __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+  // Perform tail call to the entry.
+  __ TailCallRuntime(
+      ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
  }



Modified: branches/experimental/toiger/src/simulator-arm.cc
==============================================================================
--- branches/experimental/toiger/src/simulator-arm.cc   (original)
+++ branches/experimental/toiger/src/simulator-arm.cc   Fri Nov 14 04:47:25  
2008
@@ -48,11 +48,7 @@
  // SScanF not beeing implemented in a platform independent was through
  // ::v8::internal::OS in the same way as SNPrintF is that the Windows C  
Run-Time
  // Library does not provide vsscanf.
-#ifdef WIN32
-#define SScanF sscanf_s
-#else
  #define SScanF sscanf  // NOLINT
-#endif

  // The Debugger class is used by the simulator while debugging simulated  
ARM
  // code.
@@ -382,19 +378,20 @@
  }


-// This is the Simulator singleton. Currently only one thread is supported  
by
-// V8. If we had multiple threads, then we should have a Simulator  
instance on
-// a per thread basis.
-static Simulator* the_sim = NULL;
+// Create one simulator per thread and keep it in thread local storage.
+static v8::internal::Thread::LocalStorageKey simulator_key =
+    v8::internal::Thread::CreateThreadLocalKey();

-
-// Get the active Simulator for the current thread. See comment above about
-// using a singleton currently.
+// Get the active Simulator for the current thread.
  Simulator* Simulator::current() {
-  if (the_sim == NULL) {
-    the_sim = new Simulator();
+  Simulator* sim = reinterpret_cast<Simulator*>(
+      v8::internal::Thread::GetThreadLocal(simulator_key));
+  if (sim == NULL) {
+    // TODO(146): delete the simulator object when a thread goes away.
+    sim = new Simulator();
+    v8::internal::Thread::SetThreadLocal(simulator_key, sim);
    }
-  return the_sim;
+  return sim;
  }


@@ -1495,7 +1492,7 @@


  //
-void Simulator::execute() {
+void Simulator::Execute() {
    // Get the PC to simulate. Cannot use the accessor here as we need the
    // raw PC value and not the one used as input to arithmetic instructions.
    int program_counter = get_pc();
@@ -1527,8 +1524,8 @@
  }


-Object* Simulator::call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
-                           int32_t p3, int32_t p4) {
+Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
+                        int32_t p3, int32_t p4) {
    // Setup parameters
    set_register(r0, p0);
    set_register(r1, p1);
@@ -1570,7 +1567,7 @@
    set_register(r11, callee_saved_value);

    // Start the simulation
-  execute();
+  Execute();

    // Check that the callee-saved registers have been preserved.
    CHECK_EQ(get_register(r4), callee_saved_value);

Modified: branches/experimental/toiger/src/simulator-arm.h
==============================================================================
--- branches/experimental/toiger/src/simulator-arm.h    (original)
+++ branches/experimental/toiger/src/simulator-arm.h    Fri Nov 14 04:47:25  
2008
@@ -54,7 +54,7 @@
  // When running with the simulator transition into simulated execution at  
this
  // point.
  #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
-  assembler::arm::Simulator::current()->call((int32_t)entry, (int32_t)p0, \
+  assembler::arm::Simulator::current()->Call((int32_t)entry, (int32_t)p0, \
      (int32_t)p1, (int32_t)p2, (int32_t)p3, (int32_t)p4)

  // The simulator has its own stack. Thus it has a different stack limit  
from
@@ -103,12 +103,12 @@
    uintptr_t StackLimit() const;

    // Executes ARM instructions until the PC reaches end_sim_pc.
-  void execute();
+  void Execute();

    // V8 generally calls into generated code with 5 parameters. This is a
    // convenience funtion, which sets up the simulator state and grabs the
    // result on return.
-  v8::internal::Object* call(int32_t entry, int32_t p0, int32_t p1,
+  v8::internal::Object* Call(int32_t entry, int32_t p0, int32_t p1,
                               int32_t p2, int32_t p3, int32_t p4);

   private:

Modified: branches/experimental/toiger/src/stub-cache-arm.cc
==============================================================================
--- branches/experimental/toiger/src/stub-cache-arm.cc  (original)
+++ branches/experimental/toiger/src/stub-cache-arm.cc  Fri Nov 14 04:47:25  
2008
@@ -169,6 +169,141 @@
  }


+void StubCompiler::GenerateLoadField(MacroAssembler* masm,
+                                     JSObject* object,
+                                     JSObject* holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     int index,
+                                     Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
+  GenerateFastPropertyLoad(masm, r0, reg, holder, index);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Object* value,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
+
+  // Return the constant value.
+  __ mov(r0, Operand(Handle<Object>(value)));
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
+                                        JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register name,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        AccessorInfo* callback,
+                                        Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(ip);
+  __ push(name);  // name
+  __ push(reg);  // holder
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
+                                           JSObject* object,
+                                           JSObject* holder,
+                                           Register receiver,
+                                           Register name,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      __ CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ push(reg);  // holder
+  __ push(name);  // name
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_ic_property =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ TailCallRuntime(load_ic_property, 3);
+}
+
+
+void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
+                                           Register receiver,
+                                           Register scratch,
+                                           Label* miss_label) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss_label);
+
+  // Check that the object is a JS array.
+  __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  __ cmp(scratch, Operand(JS_ARRAY_TYPE));
+  __ b(ne, miss_label);
+
+  // Load length directly from the JS array.
+  __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind)  
{
+  ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+  Code* code = NULL;
+  if (kind == Code::LOAD_IC) {
+    code = Builtins::builtin(Builtins::LoadIC_Miss);
+  } else {
+    code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+  }
+
+  Handle<Code> ic(code);
+  __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
  #undef __

  #define __ masm()->
@@ -633,20 +768,9 @@

    __ ldr(r0, MemOperand(sp, 0));

-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-  GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
-  __ Ret();
-
-  // Handle load cache miss.
+  GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
    __ bind(&miss);
-  __ ldr(r0, MemOperand(sp));  // restore receiver
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);

    // Return the generated code.
    return GetCode(FIELD);
@@ -666,29 +790,9 @@
    Label miss;

    __ ldr(r0, MemOperand(sp, 0));
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
-  // Push the arguments on the JS stack of the caller.
-  __ push(r0);  // receiver
-  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
-  __ push(ip);
-  __ push(r2);  // name
-  __ push(reg);  // holder
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_callback_property =
-      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
-  __ TailCallRuntime(load_callback_property, 4);
-
-  // Handle load cache miss.
+  GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback,  
&miss);
    __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);

    // Return the generated code.
    return GetCode(CALLBACKS);
@@ -708,21 +812,10 @@
    Label miss;

    __ ldr(r0, MemOperand(sp, 0));
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
-  // Return the constant value.
-  __ mov(r0, Operand(Handle<Object>(value)));
-  __ Ret();

-  // Handle load cache miss.
+  GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
    __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);

    // Return the generated code.
    return GetCode(CONSTANT_FUNCTION);
@@ -742,27 +835,10 @@
    Label miss;

    __ ldr(r0, MemOperand(sp, 0));
-  // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the maps haven't changed.
-  Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
-  // Push the arguments on the JS stack of the caller.
-  __ push(r0);  // receiver
-  __ push(reg);  // holder
-  __ push(r2);  // name
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_ic_property =
-      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
-  __ TailCallRuntime(load_ic_property, 3);

-  // Handle load cache miss.
+  GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
    __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  GenerateLoadMiss(masm(), Code::LOAD_IC);

    // Return the generated code.
    return GetCode(INTERCEPTOR);
@@ -775,8 +851,25 @@
                                                  JSObject* receiver,
                                                  JSObject* holder,
                                                  int index) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(FIELD);
  }


@@ -784,8 +877,26 @@
                                                     JSObject* receiver,
                                                     JSObject* holder,
                                                     AccessorInfo* callback)  
{
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
+                       r1, callback, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
  }


@@ -793,45 +904,126 @@
                                                     JSObject* receiver,
                                                     JSObject* holder,
                                                     Object* value) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  // Return the generated code.
+  return GetCode(CONSTANT_FUNCTION);
  }


  Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
                                                        JSObject* holder,
                                                        String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(INTERCEPTOR);
  }


  Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Label miss;
+
+  // Check the key is the cached one
+  __ ldr(r2, MemOperand(sp, 0));
+  __ ldr(r0, MemOperand(sp, kPointerSize));
+
+  __ cmp(r2, Operand(Handle<String>(name)));
+  __ b(ne, &miss);
+
+  GenerateLoadArrayLength(masm(), r0, r3, &miss);
+  __ bind(&miss);
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
  }


+// TODO(1224671): implement the fast case.
  Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
  }


+// TODO(1224671): implement the fast case.
  Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
+  // ----------- S t a t e -------------
+  //  -- lr    : return address
+  //  -- sp[0] : key
+  //  -- sp[4] : receiver
+  // -----------------------------------
+  HandleScope scope;
+  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+  return GetCode(CALLBACKS);
  }


+// TODO(1224671): implement the fast case.
  Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
                                                    int index,
                                                    Map* transition,
                                                    String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
-}
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r2    : name
+  //  -- lr    : return address
+  //  -- [sp]  : receiver
+  // -----------------------------------
+  HandleScope scope;
+  Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+  __ Jump(ic, RelocInfo::CODE_TARGET);

+  // Return the generated code.
+  return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
+}


  #undef __

Modified: branches/experimental/toiger/src/top.cc
==============================================================================
--- branches/experimental/toiger/src/top.cc     (original)
+++ branches/experimental/toiger/src/top.cc     Fri Nov 14 04:47:25 2008
@@ -253,7 +253,30 @@
  }


+// There are cases where the C stack is separated from JS stack (ARM  
simulator).
+// To figure out the order of top-most JS try-catch handler and the  
top-most C
+// try-catch handler, the C try-catch handler keeps a reference to the  
top-most
+// JS try_catch handler when it was created.
+//
+// Here is a picture to explain the idea:
+//   Top::thread_local_.handler_        
Top::thread_local_.try_catch_handler_
+//
+//             |                                         |
+//             v                                         v
+//
+//      | JS handler  |                        | C try_catch handler |
+//      |    next     |--+           +-------- |    js_handler_      |
+//                       |           |         |      next_          |--+
+//                       |           |                                  |
+//      | JS handler  |--+ <---------+                                  |
+//      |    next     |
+//
+// If the top-most JS try-catch handler is not equal to
+// Top::thread_local_.try_catch_handler_.js_handler_, it means the JS  
handler
+// is on the top. Otherwise, it means the C try-catch handler is on the  
top.
+//
  void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
+  that->js_handler_ = thread_local_.handler_;  // casted to void*
    thread_local_.try_catch_handler_ = that;
  }

@@ -719,8 +742,7 @@
    // address of the external handler so we can compare the address to
    // determine which one is closer to the top of the stack.
    bool has_external_handler = (thread_local_.try_catch_handler_ != NULL);
-  Address external_handler_address =
-      reinterpret_cast<Address>(thread_local_.try_catch_handler_);
+  v8::TryCatch* try_catch = thread_local_.try_catch_handler_;

    // NOTE: The stack is assumed to grown towards lower addresses. If
    // the handler is at a higher address than the external address it
@@ -732,10 +754,12 @@
    }

    // The exception has been externally caught if and only if there is
-  // an external handler which is above any JavaScript try-catch but NOT
-  // try-finally handlers.
+  // an external handler which is on top of the top-most try-catch
+  // handler.
+  //
+  // See comments in RegisterTryCatchHandler for details.
    *is_caught_externally = has_external_handler &&
-      (handler == NULL || handler->address() > external_handler_address);
+      (handler == NULL || handler == try_catch->js_handler_);

    // If we have a try-catch handler then the exception is caught in
    // JavaScript code.
@@ -745,7 +769,7 @@
    // exception if it isn't caught by JavaScript code.
    if (!has_external_handler) return is_uncaught_by_js;

-  if (is_uncaught_by_js || handler->address() > external_handler_address) {
+  if (is_uncaught_by_js || handler == try_catch->js_handler_) {
      // Only report the exception if the external handler is verbose.
      return thread_local_.try_catch_handler_->is_verbose_;
    } else {

Modified: branches/experimental/toiger/test/cctest/cctest.status
==============================================================================
--- branches/experimental/toiger/test/cctest/cctest.status      (original)
+++ branches/experimental/toiger/test/cctest/cctest.status      Fri Nov 14  
04:47:25 2008
@@ -34,7 +34,6 @@

  test-debug: SKIP
  test-serialize: SKIP
-test-api: SKIP

  # BUG(113): Test seems flaky on ARM.
  test-spaces/LargeObjectSpace: PASS || FAIL

Modified: branches/experimental/toiger/tools/visual_studio/arm.vsprops
==============================================================================
--- branches/experimental/toiger/tools/visual_studio/arm.vsprops        
(original)
+++ branches/experimental/toiger/tools/visual_studio/arm.vsprops        Fri Nov 
14  
04:47:25 2008
@@ -7,5 +7,6 @@
        <Tool
                Name="VCCLCompilerTool"
                PreprocessorDefinitions="ARM"
+               DisableSpecificWarnings="4996"
        />
  </VisualStudioPropertySheet>

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to