Version 1.3.0.

Allowed RegExp objects to be called as functions (issue 132).

Fixed issue where global property cells would escape after detaching the global object; see http://crbug.com/16276.

Added support for stepping into setters and getters in the debugger.

Changed the debugger to avoid stopping in its own JavaScript code and in the code of built-in functions.

Fixed issue 345 by avoiding duplicate escaping labels.

Fixed ARM code generator crash in short-circuited boolean expressions and added regression tests.

Added an external allocation limit to avoid issues where small V8 objects would hold on to large amounts of external memory without causing garbage collections.

Finished more of the inline caching stubs for x64 targets. 


git-svn-id: http://v8.googlecode.com/svn/trunk@2537 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 3f7ccf5..5f8149e 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -2897,7 +2897,7 @@
     __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
 
     // Write to the indexed properties array.
-    int offset = i * kPointerSize + Array::kHeaderSize;
+    int offset = i * kPointerSize + FixedArray::kHeaderSize;
     __ str(r0, FieldMemOperand(r1, offset));
 
     // Update the write barrier for the array address.
@@ -3737,7 +3737,8 @@
     }
     frame_->EmitPush(r0);  // r0 has result
   }
-  ASSERT((has_cc() && frame_->height() == original_height) ||
+  ASSERT(!has_valid_frame() ||
+         (has_cc() && frame_->height() == original_height) ||
          (!has_cc() && frame_->height() == original_height + 1));
 }
 
@@ -3871,22 +3872,12 @@
                           &is_true,
                           false_target(),
                           false);
-    if (has_cc()) {
-      Branch(false, false_target());
-
-      // Evaluate right side expression.
-      is_true.Bind();
-      LoadConditionAndSpill(node->right(),
-                            NOT_INSIDE_TYPEOF,
-                            true_target(),
-                            false_target(),
-                            false);
-
-    } else {
+    if (has_valid_frame() && !has_cc()) {
+      // The left-hand side result is on top of the virtual frame.
       JumpTarget pop_and_continue;
       JumpTarget exit;
 
-      __ ldr(r0, frame_->Top());  // dup the stack top
+      __ ldr(r0, frame_->Top());  // Duplicate the stack top.
       frame_->EmitPush(r0);
       // Avoid popping the result if it converts to 'false' using the
       // standard ToBoolean() conversion as described in ECMA-262,
@@ -3904,6 +3895,22 @@
 
       // Exit (always with a materialized value).
       exit.Bind();
+    } else if (has_cc() || is_true.is_linked()) {
+      // The left-hand side is either (a) partially compiled to
+      // control flow with a final branch left to emit or (b) fully
+      // compiled to control flow and possibly true.
+      if (has_cc()) {
+        Branch(false, false_target());
+      }
+      is_true.Bind();
+      LoadConditionAndSpill(node->right(),
+                            NOT_INSIDE_TYPEOF,
+                            true_target(),
+                            false_target(),
+                            false);
+    } else {
+      // Nothing to do.
+      ASSERT(!has_valid_frame() && !has_cc() && !is_true.is_linked());
     }
 
   } else if (op == Token::OR) {
@@ -3913,18 +3920,8 @@
                           true_target(),
                           &is_false,
                           false);
-    if (has_cc()) {
-      Branch(true, true_target());
-
-      // Evaluate right side expression.
-      is_false.Bind();
-      LoadConditionAndSpill(node->right(),
-                            NOT_INSIDE_TYPEOF,
-                            true_target(),
-                            false_target(),
-                            false);
-
-    } else {
+    if (has_valid_frame() && !has_cc()) {
+      // The left-hand side result is on top of the virtual frame.
       JumpTarget pop_and_continue;
       JumpTarget exit;
 
@@ -3946,6 +3943,22 @@
 
       // Exit (always with a materialized value).
       exit.Bind();
+    } else if (has_cc() || is_false.is_linked()) {
+      // The left-hand side is either (a) partially compiled to
+      // control flow with a final branch left to emit or (b) fully
+      // compiled to control flow and possibly false.
+      if (has_cc()) {
+        Branch(true, true_target());
+      }
+      is_false.Bind();
+      LoadConditionAndSpill(node->right(),
+                            NOT_INSIDE_TYPEOF,
+                            true_target(),
+                            false_target(),
+                            false);
+    } else {
+      // Nothing to do.
+      ASSERT(!has_valid_frame() && !has_cc() && !is_false.is_linked());
     }
 
   } else {
@@ -3989,7 +4002,8 @@
     }
     frame_->EmitPush(r0);
   }
-  ASSERT((has_cc() && frame_->height() == original_height) ||
+  ASSERT(!has_valid_frame() ||
+         (has_cc() && frame_->height() == original_height) ||
          (!has_cc() && frame_->height() == original_height + 1));
 }
 
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 2ca74a9..82a2bec 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -77,6 +77,13 @@
   __ cmp(r3, Operand(JS_GLOBAL_PROXY_TYPE));
   __ b(eq, miss);
 
+  // Possible work-around for http://crbug.com/16276.
+  // See also: http://codereview.chromium.org/155418.
+  __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE));
+  __ b(eq, miss);
+  __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
+  __ b(eq, miss);
+
   // Check that the properties array is a dictionary.
   __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset));
   __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset));
@@ -84,14 +91,14 @@
   __ b(ne, miss);
 
   // Compute the capacity mask.
-  const int kCapacityOffset =
-      Array::kHeaderSize + StringDictionary::kCapacityIndex * kPointerSize;
+  const int kCapacityOffset = StringDictionary::kHeaderSize +
+      StringDictionary::kCapacityIndex * kPointerSize;
   __ ldr(r3, FieldMemOperand(t0, kCapacityOffset));
   __ mov(r3, Operand(r3, ASR, kSmiTagSize));  // convert smi to int
   __ sub(r3, r3, Operand(1));
 
-  const int kElementsStartOffset =
-      Array::kHeaderSize + StringDictionary::kElementsStartIndex * kPointerSize;
+  const int kElementsStartOffset = StringDictionary::kHeaderSize +
+      StringDictionary::kElementsStartIndex * kPointerSize;
 
   // Generate an unrolled loop that performs a few probes before
   // giving up. Measurements done on Gmail indicate that 2 probes
@@ -592,7 +599,7 @@
 
   // Fast case: Do the load.
   __ bind(&fast);
-  __ add(r3, r1, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r3, r1, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ ldr(r0, MemOperand(r3, r0, LSL, kPointerSizeLog2));
   __ cmp(r0, Operand(Factory::the_hole_value()));
   // In case the loaded value is the_hole we have to consult GetProperty
@@ -659,9 +666,9 @@
   // Untag the key (for checking against untagged length in the fixed array).
   __ mov(r1, Operand(r1, ASR, kSmiTagSize));
   // Compute address to store into and check array bounds.
-  __ add(r2, r3, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r3, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2));
-  __ ldr(ip, FieldMemOperand(r3, Array::kLengthOffset));
+  __ ldr(ip, FieldMemOperand(r3, FixedArray::kLengthOffset));
   __ cmp(r1, Operand(ip));
   __ b(lo, &fast);
 
@@ -689,7 +696,7 @@
   __ mov(r3, Operand(r2));
   // NOTE: Computing the address to store into must take the fact
   // that the key has been incremented into account.
-  int displacement = Array::kHeaderSize - kHeapObjectTag -
+  int displacement = FixedArray::kHeaderSize - kHeapObjectTag -
       ((1 << kSmiTagSize) * 2);
   __ add(r2, r2, Operand(displacement));
   __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
@@ -714,7 +721,7 @@
   __ cmp(r1, Operand(ip));
   __ b(hs, &extra);
   __ mov(r3, Operand(r2));
-  __ add(r2, r2, Operand(Array::kHeaderSize - kHeapObjectTag));
+  __ add(r2, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   __ add(r2, r2, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
 
 
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 47e2749..875c91e 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -226,7 +226,7 @@
   // Add the page header (including remembered set), array header, and array
   // body size to the page address.
   add(object, object, Operand(Page::kObjectStartOffset
-                              + Array::kHeaderSize));
+                              + FixedArray::kHeaderSize));
   add(object, object, Operand(scratch));
 
   bind(&fast);
diff --git a/src/arm/register-allocator-arm-inl.h b/src/arm/register-allocator-arm-inl.h
index d98818f..4691f29 100644
--- a/src/arm/register-allocator-arm-inl.h
+++ b/src/arm/register-allocator-arm-inl.h
@@ -60,7 +60,7 @@
 
 int RegisterAllocator::ToNumber(Register reg) {
   ASSERT(reg.is_valid() && !IsReserved(reg));
-  static int numbers[] = {
+  const int kNumbers[] = {
     0,   // r0
     1,   // r1
     2,   // r2
@@ -78,15 +78,15 @@
     11,  // lr
     -1   // pc
   };
-  return numbers[reg.code()];
+  return kNumbers[reg.code()];
 }
 
 
 Register RegisterAllocator::ToRegister(int num) {
   ASSERT(num >= 0 && num < kNumRegisters);
-  static Register registers[] =
+  const Register kRegisters[] =
       { r0, r1, r2, r3, r4, r5, r6, r7, r9, r10, ip, lr };
-  return registers[num];
+  return kRegisters[num];
 }
 
 
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 6d9ace8..d6650c9 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -164,7 +164,7 @@
     __ ldr(dst, FieldMemOperand(src, offset));
   } else {
     // Calculate the offset into the properties array.
-    int offset = index * kPointerSize + Array::kHeaderSize;
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
     __ ldr(dst, FieldMemOperand(src, JSObject::kPropertiesOffset));
     __ ldr(dst, FieldMemOperand(dst, offset));
   }
@@ -330,7 +330,7 @@
     __ RecordWrite(receiver_reg, name_reg, scratch);
   } else {
     // Write to the properties array.
-    int offset = index * kPointerSize + Array::kHeaderSize;
+    int offset = index * kPointerSize + FixedArray::kHeaderSize;
     // Get the properties array
     __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
     __ str(r0, FieldMemOperand(scratch, offset));
@@ -1121,8 +1121,6 @@
 }
 
 
-// TODO(1224671): IC stubs for keyed loads have not been implemented
-// for ARM.
 Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
                                                 JSObject* receiver,
                                                 JSObject* holder,