Revert r13025 and r13026 (they introduced a bug on arm and regressed octane crypto).
authormmassi@chromium.org <mmassi@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Nov 2012 10:53:03 +0000 (10:53 +0000)
committermmassi@chromium.org <mmassi@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 23 Nov 2012 10:53:03 +0000 (10:53 +0000)
BUG=

Review URL: https://chromiumcodereview.appspot.com/11316151

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13039 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/lithium-codegen-arm.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/ia32/lithium-codegen-ia32.cc
src/ic.cc
src/mips/lithium-codegen-mips.cc
src/objects-inl.h
src/objects.h
src/x64/lithium-codegen-x64.cc
test/mjsunit/array-length.js

index 94e5b576b7d7925250781f3c921dda7fd70296c4..1f6c5adb9855548186d28cfa92c0d266080b23bf 100644 (file)
@@ -4942,12 +4942,11 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
   SmallMapList* map_set = instr->hydrogen()->map_set();
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMap(reg, scratch, map, &success, instr->hydrogen()->mode());
+    __ CompareMap(reg, scratch, map, &success, REQUIRE_EXACT_MAP);
     __ b(eq, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
-                   instr->environment());
+  DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment());
   __ bind(&success);
 }
 
index 79e4a5dea0b5e0a28d83fa9c2ad5d1471c66a7c6..e5290783d5a858aef51c860bb5fdc2e19d220401 100644 (file)
@@ -2201,8 +2201,7 @@ class HLoadExternalArrayPointer: public HUnaryOperation {
 class HCheckMaps: public HTemplateInstruction<2> {
  public:
   HCheckMaps(HValue* value, Handle<Map> map, Zone* zone,
-             HValue* typecheck = NULL,
-             CompareMapMode mode = REQUIRE_EXACT_MAP) : mode_(mode) {
+             HValue* typecheck = NULL) {
     SetOperandAt(0, value);
     // If callers don't depend on a typecheck, they can pass in NULL. In that
     // case we use a copy of the |value| argument as a dummy value.
@@ -2213,8 +2212,7 @@ class HCheckMaps: public HTemplateInstruction<2> {
     SetGVNFlag(kDependsOnElementsKind);
     map_set()->Add(map, zone);
   }
-  HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone,
-             CompareMapMode mode = REQUIRE_EXACT_MAP) : mode_(mode) {
+  HCheckMaps(HValue* value, SmallMapList* maps, Zone* zone) {
     SetOperandAt(0, value);
     SetOperandAt(1, value);
     set_representation(Representation::Tagged());
@@ -2259,7 +2257,6 @@ class HCheckMaps: public HTemplateInstruction<2> {
 
   HValue* value() { return OperandAt(0); }
   SmallMapList* map_set() { return &map_set_; }
-  CompareMapMode mode() { return mode_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CheckMaps)
 
@@ -2276,7 +2273,6 @@ class HCheckMaps: public HTemplateInstruction<2> {
 
  private:
   SmallMapList map_set_;
-  CompareMapMode mode_;
 };
 
 
index ddff6c0ff5092f5836acd12791f597d03d8fa6e5..ccc11ff346c020c1f55f71173f124ef448d8adf7 100644 (file)
@@ -6591,8 +6591,6 @@ void HGraphBuilder::VisitProperty(Property* expr) {
 
   HInstruction* instr = NULL;
   if (expr->AsProperty()->IsArrayLength()) {
-    // Note that in the monomorphic case IsArrayLength() is false because we
-    // handle that it with a regular property load IC.
     HValue* array = Pop();
     AddInstruction(new(zone()) HCheckNonSmi(array));
     HInstruction* mapcheck =
@@ -6628,74 +6626,23 @@ void HGraphBuilder::VisitProperty(Property* expr) {
       map = types->first();
       if (map->is_dictionary_map()) monomorphic = false;
     }
-
-    // Try to see if this is an array length access.
-    if (name->Equals(isolate()->heap()->length_symbol())) {
-      bool is_array = false;
-      bool fast_mode = false;
-      bool map_mode = false;
-      HInstruction* mapcheck = NULL;
-
-      if (expr->IsMonomorphic()) {
-        // Even if there is more than one map they all must be element
-        // transition maps, so checking just one is ok.
-        if (map->instance_type() == JS_ARRAY_TYPE) {
-          is_array = true;
-          map_mode = true;
-          fast_mode = IsFastElementsKind(map->elements_kind());
-        }
+    if (monomorphic) {
+      Handle<JSFunction> getter;
+      Handle<JSObject> holder;
+      if (LookupGetter(map, name, &getter, &holder)) {
+        AddCheckConstantFunction(holder, Top(), map);
+        if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
+        AddInstruction(new(zone()) HPushArgument(Pop()));
+        instr = new(zone()) HCallConstantFunction(getter, 1);
       } else {
-        // Since we will emit an instance check we have to conservatively
-        // assume that some arrays will contain slow elements, so we set
-        // fast_mode to false.
-        map_mode = false;
-        fast_mode = false;
-        is_array = true;
-        for (int i = 0; i < types->length(); i++) {
-          Handle<Map> current_map = types->at(i);
-          if (current_map->instance_type() != JS_ARRAY_TYPE) {
-            is_array = false;
-            break;
-          }
-        }
-      }
-
-      // It is an array length access so we produce a HJSArrayLength.
-      if (is_array) {
-        HValue* array = Pop();
-        AddInstruction(new(zone()) HCheckNonSmi(array));
-        mapcheck = map_mode ?
-            HInstruction::cast(
-                new(zone()) HCheckMaps(array, map, zone(), NULL,
-                                       ALLOW_ELEMENT_TRANSITION_MAPS)) :
-            HInstruction::cast(
-                HCheckInstanceType::NewIsJSArray(array, zone()));
-        AddInstruction(mapcheck);
-        instr = new(zone()) HJSArrayLength(
-            array, mapcheck, fast_mode ? HType::Smi() : HType::Tagged());
+        instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map);
       }
+    } else if (types != NULL && types->length() > 1) {
+      return HandlePolymorphicLoadNamedField(expr, Pop(), types, name);
+    } else {
+      instr = BuildLoadNamedGeneric(Pop(), name, expr);
     }
 
-    // We cannot know if it was an array length access so we handle it as
-    // a regular property access.
-    if (instr == NULL) {
-      if (monomorphic) {
-        Handle<JSFunction> getter;
-        Handle<JSObject> holder;
-        if (LookupGetter(map, name, &getter, &holder)) {
-          AddCheckConstantFunction(holder, Top(), map);
-          if (FLAG_inline_accessors && TryInlineGetter(getter, expr)) return;
-          AddInstruction(new(zone()) HPushArgument(Pop()));
-          instr = new(zone()) HCallConstantFunction(getter, 1);
-        } else {
-          instr = BuildLoadNamedMonomorphic(Pop(), name, expr, map);
-        }
-      } else if (types != NULL && types->length() > 1) {
-        return HandlePolymorphicLoadNamedField(expr, Pop(), types, name);
-      } else {
-        instr = BuildLoadNamedGeneric(Pop(), name, expr);
-      }
-    }
   } else {
     CHECK_ALIVE(VisitForValue(expr->key()));
 
index 2b2cafbe3786c641472e1bd98ed8aa1ac39d0a66..3e19c39ba24de278a78f128739f899402e46735a 100644 (file)
@@ -4770,11 +4770,11 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
   SmallMapList* map_set = instr->hydrogen()->map_set();
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMap(reg, map, &success, instr->hydrogen()->mode());
+    __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP);
     __ j(equal, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment());
+  DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr->environment());
   __ bind(&success);
 }
 
index 19f6eda38b4ccb7f36fb1ed352c2a1de71d73e37..bf2a649f7f298d1e53fb53b035b5dcfb323a7ee7 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -855,6 +855,26 @@ MaybeObject* LoadIC::Load(State state,
       return Smi::FromInt(String::cast(*string)->length());
     }
 
+    // Use specialized code for getting the length of arrays.
+    if (object->IsJSArray() &&
+        name->Equals(isolate()->heap()->length_symbol())) {
+      Handle<Code> stub;
+      if (state == UNINITIALIZED) {
+        stub = pre_monomorphic_stub();
+      } else if (state == PREMONOMORPHIC) {
+        stub = isolate()->builtins()->LoadIC_ArrayLength();
+      } else if (state != MEGAMORPHIC) {
+        stub = megamorphic_stub();
+      }
+      if (!stub.is_null()) {
+        set_target(*stub);
+#ifdef DEBUG
+        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
+#endif
+      }
+      return JSArray::cast(*object)->length();
+    }
+
     // Use specialized code for getting prototype of functions.
     if (object->IsJSFunction() &&
         name->Equals(isolate()->heap()->prototype_symbol()) &&
@@ -986,17 +1006,6 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
           if (!holder->HasFastProperties()) return;
           code = isolate()->stub_cache()->ComputeLoadViaGetter(
               name, receiver, holder, Handle<JSFunction>::cast(getter));
-        } else if (holder->IsJSArray() &&
-            name->Equals(isolate()->heap()->length_symbol())) {
-          ASSERT(callback->IsForeign());
-          ASSERT(reinterpret_cast<AccessorDescriptor*>(
-              Handle<Foreign>::cast(callback)->foreign_address())
-              == &Accessors::ArrayLength);
-          // Use a "load field" IC for getting the array length.
-          // Note that the resulting code object is marked as "Code::FIELD"
-          // and not as "Code::CALLBACKS".
-          code = isolate()->stub_cache()->ComputeLoadField(
-              name, receiver, holder, JSArray::ArrayLengthIndex());
         } else {
           ASSERT(callback->IsForeign());
           // No IC support for old-style native accessors.
index f398441bed42531a3971ecc34cce1c14d322a141..e19caf34c2a901be98b7a9eb414fcb59c9e10c35 100644 (file)
@@ -4639,11 +4639,10 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
     __ CompareMapAndBranch(
-        reg, scratch, map, &success, eq, &success, instr->hydrogen()->mode());
+        reg, scratch, map, &success, eq, &success, REQUIRE_EXACT_MAP);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(reg, scratch, map, instr->hydrogen()->mode(),
-                   instr->environment());
+  DoCheckMapCommon(reg, scratch, map, REQUIRE_EXACT_MAP, instr->environment());
   __ bind(&success);
 }
 
index ec92e76e07b201bdf0e362579137c2eb4b54cf87..6e8d148661ff4053e4c9db521953ffd7f8fa13ca 100644 (file)
@@ -4669,11 +4669,6 @@ bool Code::contains(byte* inner_pointer) {
 ACCESSORS(JSArray, length, Object, kLengthOffset)
 
 
-PropertyIndex JSArray::ArrayLengthIndex() {
-  return PropertyIndex::NewHeaderIndex(kLengthOffset / kPointerSize);
-}
-
-
 ACCESSORS(JSRegExp, data, Object, kDataOffset)
 
 
index e9a1e935f5e937a40dcc81aff151585389a53a55..7d46c068589bfb707a43e93d84bf5cc74e328275 100644 (file)
@@ -8323,9 +8323,6 @@ class Foreign: public HeapObject {
 };
 
 
-class PropertyIndex;
-
-
 // The JSArray describes JavaScript Arrays
 //  Such an array can be in one of two modes:
 //    - fast, backing storage is a FixedArray and length <= elements.length();
@@ -8379,9 +8376,6 @@ class JSArray: public JSObject {
   static const int kLengthOffset = JSObject::kHeaderSize;
   static const int kSize = kLengthOffset + kPointerSize;
 
-  static inline PropertyIndex ArrayLengthIndex();
-  STATIC_ASSERT(kLengthOffset % kPointerSize == 0);
-
  private:
   // Expand the fixed array backing of a fast-case JSArray to at least
   // the requested size.
index 9feef1b9146fffcc1f31919d8919532bc6f0c7d7..13c5fa51fda9e8e7d390e69a1ba2d3b64c4313cd 100644 (file)
@@ -4537,11 +4537,11 @@ void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
   SmallMapList* map_set = instr->hydrogen()->map_set();
   for (int i = 0; i < map_set->length() - 1; i++) {
     Handle<Map> map = map_set->at(i);
-    __ CompareMap(reg, map, &success, instr->hydrogen()->mode());
+    __ CompareMap(reg, map, &success, REQUIRE_EXACT_MAP);
     __ j(equal, &success);
   }
   Handle<Map> map = map_set->last();
-  DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment());
+  DoCheckMapCommon(reg, map, REQUIRE_EXACT_MAP, instr->environment());
   __ bind(&success);
 }
 
index 7c3063ee1c0fbd2bfa4dcd2626ef4164403a0832..16867db733b6c98bb45b9428b86755d6c1e58e5d 100644 (file)
@@ -25,8 +25,6 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Flags: --allow-natives-syntax
-
 var a = [0,1,2,3];
 assertEquals(0, a.length = 0);
 
@@ -121,42 +119,3 @@ for (var i = 0; i < 7; i++) {
   t = a.length = 7;
   assertEquals(7, t);
 }
-
-function TestLengthAccess() {
-  var TestGetLength = function(a, l, getLength, getKeyedLength) {
-    assertEquals(l, getLength(a));
-    assertEquals(l, getKeyedLength(a));
-  }
-
-  var Test = function(a, l, getLength, getKeyedLength) {
-    // Make the ICs reach the state we want.
-    TestGetLength(a, l, getLength, getKeyedLength);
-    TestGetLength(a, l, getLength, getKeyedLength);
-    TestGetLength(a, l, getLength, getKeyedLength);
-    // Also test crankshaft.
-    %OptimizeFunctionOnNextCall(getLength);
-    %OptimizeFunctionOnNextCall(getKeyedLength);
-    TestGetLength(a, l, getLength, getKeyedLength);
-  }
-
-  var getLength = function(a) { return a.length; }
-  var getKeyedLength = function(a) { return a['length']; }
-  Test(new Array(4), 4, getLength, getKeyedLength);
-
-  getLength = function(a) { return a.length; }
-  getKeyedLength = function(a) { return a['length']; }
-  Test([1, 2, 3, 4], 4, getLength, getKeyedLength);
-
-  getLength = function(a) { return a.length; }
-  getKeyedLength = function(a) { return a['length']; }
-  Test(Object.create(new Array(4)), 4, getLength, getKeyedLength);
-
-  getLength = function(a) { return a.length; }
-  getKeyedLength = function(a) { return a['length']; }
-  // Set the 'length' of the global object.
-  length = 4;
-  var globalObject = (1,eval)("this");
-  Test(globalObject, 4, getLength, getKeyedLength);
-}
-TestLengthAccess();
-