Author: [EMAIL PROTECTED]
Date: Tue Oct 28 01:56:02 2008
New Revision: 619

Added:
    branches/0.3/test/mjsunit/string-compare-alignment.js
       - copied unchanged from r611,  
/branches/bleeding_edge/test/mjsunit/string-compare-alignment.js
Modified:
    branches/0.3/src/api.cc
    branches/0.3/src/builtins.cc
    branches/0.3/src/builtins.h
    branches/0.3/src/codegen-ia32.cc
    branches/0.3/src/execution.cc
    branches/0.3/src/ic-arm.cc
    branches/0.3/src/ic-ia32.cc
    branches/0.3/src/ic.cc
    branches/0.3/src/ic.h
    branches/0.3/src/jsregexp.cc
    branches/0.3/src/objects-inl.h
    branches/0.3/src/objects.cc
    branches/0.3/src/objects.h
    branches/0.3/src/runtime.js
    branches/0.3/src/stub-cache-arm.cc
    branches/0.3/src/stub-cache-ia32.cc
    branches/0.3/src/stub-cache.cc
    branches/0.3/src/stub-cache.h
    branches/0.3/src/top.cc
    branches/0.3/src/top.h
    branches/0.3/test/mjsunit/mjsunit.status

Log:
Merge in changes from version 0.4.1 to 0.3.7.
Review URL: http://codereview.chromium.org/8653

Modified: branches/0.3/src/api.cc
==============================================================================
--- branches/0.3/src/api.cc     (original)
+++ branches/0.3/src/api.cc     Tue Oct 28 01:56:02 2008
@@ -230,7 +230,13 @@

  v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
    if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
-  i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
+  // If we're passed an empty handle, we throw an undefined exception
+  // to deal more gracefully with out of memory situations.
+  if (value.IsEmpty()) {
+    i::Top::ScheduleThrow(i::Heap::undefined_value());
+  } else {
+    i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
+  }
    return v8::Undefined();
  }

@@ -2216,7 +2222,7 @@


  const char* v8::V8::GetVersion() {
-  return "0.3.6";
+  return "0.3.7";
  }



Modified: branches/0.3/src/builtins.cc
==============================================================================
--- branches/0.3/src/builtins.cc        (original)
+++ branches/0.3/src/builtins.cc        Tue Oct 28 01:56:02 2008
@@ -465,18 +465,8 @@
  }


-static void Generate_LoadIC_ShortStringLength(MacroAssembler* masm) {
-  LoadIC::GenerateShortStringLength(masm);
-}
-
-
-static void Generate_LoadIC_MediumStringLength(MacroAssembler* masm) {
-  LoadIC::GenerateMediumStringLength(masm);
-}
-
-
-static void Generate_LoadIC_LongStringLength(MacroAssembler* masm) {
-  LoadIC::GenerateLongStringLength(masm);
+static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
+  LoadIC::GenerateStringLength(masm);
  }



Modified: branches/0.3/src/builtins.h
==============================================================================
--- branches/0.3/src/builtins.h (original)
+++ branches/0.3/src/builtins.h Tue Oct 28 01:56:02 2008
@@ -69,9 +69,7 @@
    V(LoadIC_PreMonomorphic,      LOAD_IC, PREMONOMORPHIC)       \
    V(LoadIC_Normal,              LOAD_IC, MONOMORPHIC)          \
    V(LoadIC_ArrayLength,         LOAD_IC, MONOMORPHIC)          \
-  V(LoadIC_ShortStringLength,   LOAD_IC, MONOMORPHIC)          \
-  V(LoadIC_MediumStringLength,  LOAD_IC, MONOMORPHIC)          \
-  V(LoadIC_LongStringLength,    LOAD_IC, MONOMORPHIC)          \
+  V(LoadIC_StringLength,        LOAD_IC, MONOMORPHIC)          \
    V(LoadIC_FunctionPrototype,   LOAD_IC, MONOMORPHIC)          \
    V(LoadIC_Megamorphic,         LOAD_IC, MEGAMORPHIC)          \
    V(LoadIC_DebugBreak,          LOAD_IC, DEBUG_BREAK)          \

Modified: branches/0.3/src/codegen-ia32.cc
==============================================================================
--- branches/0.3/src/codegen-ia32.cc    (original)
+++ branches/0.3/src/codegen-ia32.cc    Tue Oct 28 01:56:02 2008
@@ -2839,38 +2839,26 @@
    __ sar(ebx, kSmiTagSize);

    __ bind(&try_again_with_new_string);
-  // Get the type of the heap object into ecx.
+  // Get the type of the heap object into edi.
    __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
+  __ movzx_b(edi, FieldOperand(edx, Map::kInstanceTypeOffset));
    // We don't handle non-strings.
-  __ test(ecx, Immediate(kIsNotStringMask));
+  __ test(edi, Immediate(kIsNotStringMask));
    __ j(not_zero, &slow_case, not_taken);

+  // Here we make assumptions about the tag values and the shifts needed.
+  // See the comment in objects.h.
+  ASSERT(kLongStringTag == 0);
+  ASSERT(kMediumStringTag + String::kLongLengthShift ==
+             String::kMediumLengthShift);
+  ASSERT(kShortStringTag + String::kLongLengthShift ==
+             String::kShortLengthShift);
+  __ mov(ecx, Operand(edi));
+  __ and_(ecx, kStringSizeMask);
+  __ add(Operand(ecx), Immediate(String::kLongLengthShift));
    // Get the length field.
    __ mov(edx, FieldOperand(eax, String::kLengthOffset));
-  Label long_string;
-  Label medium_string;
-  Label string_length_shifted;
-  // The code assumes the tags are disjoint.
-  ASSERT((kLongStringTag & kMediumStringTag) == 0);
-  ASSERT(kShortStringTag == 0);
-  __ test(ecx, Immediate(kLongStringTag));
-  __ j(not_zero, &long_string, not_taken);
-  __ test(ecx, Immediate(kMediumStringTag));
-  __ j(not_zero, &medium_string, taken);
-  // Short string.
-  __ shr(edx, String::kShortLengthShift);
-  __ jmp(&string_length_shifted);
-
-  // Medium string.
-  __ bind(&medium_string);
-  __ shr(edx, String::kMediumLengthShift - String::kLongLengthShift);
-  // Fall through to long string.
-  __ bind(&long_string);
-  __ shr(edx, String::kLongLengthShift);
-
-  __ bind(&string_length_shifted);
-  ASSERT(kSmiTag == 0);
+  __ shr(edx);  // ecx is implicit operand.
    // edx is now the length of the string.

    // Check for index out of range.
@@ -2879,11 +2867,11 @@

    // We need special handling for non-flat strings.
    ASSERT(kSeqStringTag == 0);
-  __ test(ecx, Immediate(kStringRepresentationMask));
+  __ test(edi, Immediate(kStringRepresentationMask));
    __ j(not_zero, &not_a_flat_string, not_taken);

    // Check for 1-byte or 2-byte string.
-  __ test(ecx, Immediate(kStringEncodingMask));
+  __ test(edi, Immediate(kStringEncodingMask));
    __ j(not_zero, &ascii_string, taken);

    // 2-byte string.
@@ -2903,11 +2891,10 @@
    frame_->Push(eax);
    __ jmp(&end);

-
    // Handle non-flat strings.
    __ bind(&not_a_flat_string);
-  __ and_(ecx, kStringRepresentationMask);
-  __ cmp(ecx, kConsStringTag);
+  __ and_(edi, kStringRepresentationMask);
+  __ cmp(edi, kConsStringTag);
    __ j(not_equal, &not_a_cons_string_either, not_taken);

    // ConsString.
@@ -2916,7 +2903,7 @@
    __ jmp(&try_again_with_new_string);

    __ bind(&not_a_cons_string_either);
-  __ cmp(ecx, kSlicedStringTag);
+  __ cmp(edi, kSlicedStringTag);
    __ j(not_equal, &slow_case, not_taken);

    // SlicedString.

Modified: branches/0.3/src/execution.cc
==============================================================================
--- branches/0.3/src/execution.cc       (original)
+++ branches/0.3/src/execution.cc       Tue Oct 28 01:56:02 2008
@@ -91,10 +91,12 @@
    value->Verify();
  #endif

-  // Update the pending exception and external caught flag and return the  
value.
+  // Update the pending exception flag and return the value.
    *has_pending_exception = value->IsException();
    ASSERT(*has_pending_exception == Top::has_pending_exception());
-  Top::propagate_external_caught();
+  if (*has_pending_exception) {
+    Top::setup_external_caught();
+  }

    // If the pending exception is OutOfMemoryException set out_of_memory in
    // the global context.  Note: We have to mark the global context here

Modified: branches/0.3/src/ic-arm.cc
==============================================================================
--- branches/0.3/src/ic-arm.cc  (original)
+++ branches/0.3/src/ic-arm.cc  Tue Oct 28 01:56:02 2008
@@ -156,103 +156,61 @@
  }


-void LoadIC::GenerateShortStringLength(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- [sp]  : receiver
-  // -----------------------------------
-
-  Label miss;
-
-  __ ldr(r0, MemOperand(sp, 0));
-
+// Generate code to check if an object is a string.  If the object is
+// a string, the map's instance type is left in the scratch1 register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch1,
+                                Register scratch2,
+                                Label* smi,
+                                Label* non_string_object) {
    // Check that the receiver isn't a smi.
-  __ tst(r0, Operand(kSmiTagMask));
-  __ b(eq, &miss);
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, smi);

-  // Check that the object is a short string.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-  __ and_(r1, r1, Operand(kIsNotStringMask | kStringSizeMask));
+  // Check that the object is a string.
+  __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
+  __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
    // The cast is to resolve the overload for the argument of 0x0.
-  __ cmp(r1, Operand(static_cast<int32_t>(kStringTag | kShortStringTag)));
-  __ b(ne, &miss);
-
-  // Load length directly from the string.
-  __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset));
-  __ mov(r0, Operand(r0, LSR, String::kShortLengthShift));
-  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
-  __ Ret();
-
-  // Cache miss: Jump to runtime.
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
+  __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
+  __ b(ne, non_string_object);
  }


-void LoadIC::GenerateMediumStringLength(MacroAssembler* masm) {
+void LoadIC::GenerateStringLength(MacroAssembler* masm) {
    // ----------- S t a t e -------------
    //  -- r2    : name
    //  -- lr    : return address
    //  -- [sp]  : receiver
    // -----------------------------------

-  Label miss;
+  Label miss, load_length, check_wrapper;

    __ 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 medium string.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-  __ and_(r1, r1, Operand(kIsNotStringMask | kStringSizeMask));
-  __ cmp(r1, Operand(kStringTag | kMediumStringTag));
-  __ b(ne, &miss);
+  // Check if the object is a string.
+  GenerateStringCheck(masm, r0, r1, r3, &miss, &check_wrapper);

    // Load length directly from the string.
+  __ bind(&load_length);
+  __ and_(r1, r1, Operand(kStringSizeMask));
+  __ add(r1, r1, Operand(String::kHashShift));
    __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset));
-  __ mov(r0, Operand(r0, LSR, String::kMediumLengthShift));
+  __ mov(r0, Operand(r0, LSR, r1));
    __ mov(r0, Operand(r0, LSL, kSmiTagSize));
    __ Ret();

-  // Cache miss: Jump to runtime.
-  __ bind(&miss);
-  Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
-  __ Jump(ic, RelocInfo::CODE_TARGET);
-}
-
-
-void LoadIC::GenerateLongStringLength(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- r2    : name
-  //  -- lr    : return address
-  //  -- [sp]  : receiver
-  // -----------------------------------
-
-  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 object is a long string.
-  __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
-  __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
-  __ and_(r1, r1, Operand(kIsNotStringMask | kStringSizeMask));
-  __ cmp(r1, Operand(kStringTag | kLongStringTag));
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(r0, Operand(JS_VALUE_TYPE));
    __ b(ne, &miss);

-  // Load length directly from the string.
-  __ ldr(r0, FieldMemOperand(r0, String::kLengthOffset));
-  __ mov(r0, Operand(r0, LSR, String::kLongLengthShift));
-  __ mov(r0, Operand(r0, LSL, kSmiTagSize));
-  __ Ret();
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
+  GenerateStringCheck(masm, r0, r1, r3, &miss, &miss);
+  __ b(&load_length);

    // Cache miss: Jump to runtime.
    __ bind(&miss);

Modified: branches/0.3/src/ic-ia32.cc
==============================================================================
--- branches/0.3/src/ic-ia32.cc (original)
+++ branches/0.3/src/ic-ia32.cc Tue Oct 28 01:56:02 2008
@@ -138,7 +138,7 @@
  }


-void LoadIC::GenerateShortStringLength(MacroAssembler* masm) {
+void LoadIC::GenerateStringLength(MacroAssembler* masm) {
    // ----------- S t a t e -------------
    //  -- ecx    : name
    //  -- esp[0] : return address
@@ -149,41 +149,7 @@

    __ mov(eax, Operand(esp, kPointerSize));

-  StubCompiler::GenerateLoadShortStringLength(masm, eax, edx, &miss);
-  __ bind(&miss);
-  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
-void LoadIC::GenerateMediumStringLength(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- ecx    : name
-  //  -- esp[0] : return address
-  //  -- esp[4] : receiver
-  // -----------------------------------
-
-  Label miss;
-
-  __ mov(eax, Operand(esp, kPointerSize));
-
-  StubCompiler::GenerateLoadMediumStringLength(masm, eax, edx, &miss);
-  __ bind(&miss);
-  StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
-}
-
-
-void LoadIC::GenerateLongStringLength(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- ecx    : name
-  //  -- esp[0] : return address
-  //  -- esp[4] : receiver
-  // -----------------------------------
-
-  Label miss;
-
-  __ mov(eax, Operand(esp, kPointerSize));
-
-  StubCompiler::GenerateLoadLongStringLength(masm, eax, edx, &miss);
+  StubCompiler::GenerateLoadStringLength(masm, eax, edx, &miss);
    __ bind(&miss);
    StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
  }

Modified: branches/0.3/src/ic.cc
==============================================================================
--- branches/0.3/src/ic.cc      (original)
+++ branches/0.3/src/ic.cc      Tue Oct 28 01:56:02 2008
@@ -453,20 +453,22 @@
    }

    if (FLAG_use_ic) {
-    // Use specialized code for getting the length of strings.
-    if (object->IsString() && name->Equals(Heap::length_symbol())) {
+    // Use specialized code for getting the length of strings and
+    // string wrapper objects.  The length property of string wrapper
+    // objects is read-only and therefore always returns the length of
+    // the underlying string value.  See ECMA-262 15.5.5.1.
+    if ((object->IsString() || object->IsStringWrapper()) &&
+        name->Equals(Heap::length_symbol())) {
+      HandleScope scope;
+      // Get the string if we have a string wrapper object.
+      if (object->IsJSValue()) {
+        object = Handle<Object>(Handle<JSValue>::cast(object)->value());
+      }
  #ifdef DEBUG
        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
  #endif
        Code* target = NULL;
-      if (object->IsShortString()) {
-        target = Builtins::builtin(Builtins::LoadIC_ShortStringLength);
-      } else if (object->IsMediumString()) {
-        target = Builtins::builtin(Builtins::LoadIC_MediumStringLength);
-      } else {
-        ASSERT(object->IsLongString());
-        target  = Builtins::builtin(Builtins::LoadIC_LongStringLength);
-      }
+      target = Builtins::builtin(Builtins::LoadIC_StringLength);
        set_target(target);
        StubCache::Set(*name, HeapObject::cast(*object)->map(), target);
        return Smi::FromInt(String::cast(*object)->length());
@@ -637,15 +639,7 @@
        if (object->IsString() && name->Equals(Heap::length_symbol())) {
          Handle<String> string = Handle<String>::cast(object);
          Object* code = NULL;
-        if (string->IsShortString()) {
-          code = StubCache::ComputeKeyedLoadShortStringLength(*name,  
*string);
-        } else if (string->IsMediumString()) {
-          code =
-              StubCache::ComputeKeyedLoadMediumStringLength(*name,  
*string);
-        } else {
-          ASSERT(string->IsLongString());
-          code = StubCache::ComputeKeyedLoadLongStringLength(*name,  
*string);
-        }
+        code = StubCache::ComputeKeyedLoadStringLength(*name, *string);
          if (code->IsFailure()) return code;
          set_target(Code::cast(code));
  #ifdef DEBUG

Modified: branches/0.3/src/ic.h
==============================================================================
--- branches/0.3/src/ic.h       (original)
+++ branches/0.3/src/ic.h       Tue Oct 28 01:56:02 2008
@@ -211,9 +211,7 @@

    // Specialized code generator routines.
    static void GenerateArrayLength(MacroAssembler* masm);
-  static void GenerateShortStringLength(MacroAssembler* masm);
-  static void GenerateMediumStringLength(MacroAssembler* masm);
-  static void GenerateLongStringLength(MacroAssembler* masm);
+  static void GenerateStringLength(MacroAssembler* masm);
    static void GenerateFunctionPrototype(MacroAssembler* masm);

   private:

Modified: branches/0.3/src/jsregexp.cc
==============================================================================
--- branches/0.3/src/jsregexp.cc        (original)
+++ branches/0.3/src/jsregexp.cc        Tue Oct 28 01:56:02 2008
@@ -30,11 +30,20 @@
  #include "execution.h"
  #include "factory.h"
  #include "jsregexp.h"
-#include "third_party/jscre/pcre.h"
  #include "platform.h"
  #include "runtime.h"
  #include "top.h"
  #include "compilation-cache.h"
+
+// Including pcre.h undefines DEBUG to avoid getting debug output from
+// the JSCRE implementation. Make sure to redefine it in debug mode
+// after having included the header file.
+#ifdef DEBUG
+#include "third_party/jscre/pcre.h"
+#define DEBUG
+#else
+#include "third_party/jscre/pcre.h"
+#endif

  namespace v8 { namespace internal {


Modified: branches/0.3/src/objects-inl.h
==============================================================================
--- branches/0.3/src/objects-inl.h      (original)
+++ branches/0.3/src/objects-inl.h      Tue Oct 28 01:56:02 2008
@@ -301,6 +301,11 @@
  }


+bool Object::IsStringWrapper() {
+  return IsJSValue() && JSValue::cast(this)->value()->IsString();
+}
+
+
  bool Object::IsProxy() {
    return Object::IsHeapObject()
      && HeapObject::cast(this)->map()->instance_type() == PROXY_TYPE;
@@ -1261,36 +1266,22 @@
  int String::length() {
    uint32_t len = READ_INT_FIELD(this, kLengthOffset);

-  switch (size_tag()) {
-    case kShortStringTag:
-      return  len >> kShortLengthShift;
-    case kMediumStringTag:
-      return len >> kMediumLengthShift;
-    case kLongStringTag:
-      return len >> kLongLengthShift;
-    default:
-      break;
-  }
-  UNREACHABLE();
-  return 0;
+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
+  return len >> (size_tag() + kLongLengthShift);
  }


  void String::set_length(int value) {
-  switch (size_tag()) {
-    case kShortStringTag:
-      WRITE_INT_FIELD(this, kLengthOffset, value << kShortLengthShift);
-      break;
-    case kMediumStringTag:
-      WRITE_INT_FIELD(this, kLengthOffset, value << kMediumLengthShift);
-      break;
-    case kLongStringTag:
-      WRITE_INT_FIELD(this, kLengthOffset, value << kLongLengthShift);
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
+  WRITE_INT_FIELD(this,
+                  kLengthOffset,
+                  value << (size_tag() + kLongLengthShift));
  }


@@ -1474,21 +1465,14 @@
  int SeqTwoByteString::SeqTwoByteStringSize(Map* map) {
    uint32_t length = READ_INT_FIELD(this, kLengthOffset);

+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
    // Use the map (and not 'this') to compute the size tag, since
    // TwoByteStringSize is called during GC when maps are encoded.
-  switch (map_size_tag(map)) {
-    case kShortStringTag:
-      length = length >> kShortLengthShift;
-      break;
-    case kMediumStringTag:
-      length = length >> kMediumLengthShift;
-      break;
-    case kLongStringTag:
-      length = length >> kLongLengthShift;
-      break;
-    default:
-      break;
-  }
+  length >>= map_size_tag(map) + kLongLengthShift;
+
    return SizeFor(length);
  }

@@ -1496,21 +1480,13 @@
  int SeqAsciiString::SeqAsciiStringSize(Map* map) {
    uint32_t length = READ_INT_FIELD(this, kLengthOffset);

+  ASSERT(kShortStringTag + kLongLengthShift == kShortLengthShift);
+  ASSERT(kMediumStringTag + kLongLengthShift == kMediumLengthShift);
+  ASSERT(kLongStringTag == 0);
+
    // Use the map (and not 'this') to compute the size tag, since
    // AsciiStringSize is called during GC when maps are encoded.
-  switch (map_size_tag(map)) {
-    case kShortStringTag:
-      length = length >> kShortLengthShift;
-      break;
-    case kMediumStringTag:
-      length = length >> kMediumLengthShift;
-      break;
-    case kLongStringTag:
-      length = length >> kLongLengthShift;
-      break;
-    default:
-      break;
-  }
+  length >>= map_size_tag(map) + kLongLengthShift;

    return SizeFor(length);
  }

Modified: branches/0.3/src/objects.cc
==============================================================================
--- branches/0.3/src/objects.cc (original)
+++ branches/0.3/src/objects.cc Tue Oct 28 01:56:02 2008
@@ -3912,10 +3912,12 @@
      } else {
        payload = v8::internal::HashField(GetHash(), false);
      }
-    return (payload & 0x00FFFFFF) | (length_ << String::kShortLengthShift);
+    return (payload & ((1 << String::kShortLengthShift) - 1)) |
+           (length_ << String::kShortLengthShift);
    } else if (length_ <= String::kMaxMediumStringSize) {
      uint32_t payload = v8::internal::HashField(GetHash(), false);
-    return (payload & 0x0000FFFF) | (length_ <<  
String::kMediumLengthShift);
+    return (payload & ((1 << String::kMediumLengthShift) - 1)) |
+           (length_ << String::kMediumLengthShift);
    } else {
      return v8::internal::HashField(length_, false);
    }

Modified: branches/0.3/src/objects.h
==============================================================================
--- branches/0.3/src/objects.h  (original)
+++ branches/0.3/src/objects.h  Tue Oct 28 01:56:02 2008
@@ -393,29 +393,30 @@
  const uint32_t kStringTag = 0x0;
  const uint32_t kNotStringTag = 0x80;

-// If bit 7 is clear, bits 5 and 6 are the string's size (short, medium, or
-// long).
-const uint32_t kStringSizeMask = 0x60;
-const uint32_t kShortStringTag = 0x0;
-const uint32_t kMediumStringTag = 0x20;
-const uint32_t kLongStringTag = 0x40;
-
-// If bit 7 is clear, bit 4 indicates that the string is a symbol (if set)  
or
+// If bit 7 is clear, bit 5 indicates that the string is a symbol (if set)  
or
  // not (if cleared).
-const uint32_t kIsSymbolMask = 0x10;
+const uint32_t kIsSymbolMask = 0x20;
  const uint32_t kNotSymbolTag = 0x0;
-const uint32_t kSymbolTag = 0x10;
+const uint32_t kSymbolTag = 0x20;

-// If bit 7 is clear, and the string representation is a sequential string,
-// then bit 3 indicates whether the string consists of two-byte characters  
or
-// one-byte characters.
-const uint32_t kStringEncodingMask = 0x8;
+// If bit 7 is clear, bits 3 and 4 are the string's size (short, medium or
+// long).  These values are very special in that they are also used to  
shift
+// the length field to get the length, removing the hash value.  This  
avoids
+// using if or switch when getting the length of a string.
+const uint32_t kStringSizeMask = 0x18;
+const uint32_t kShortStringTag = 0x18;
+const uint32_t kMediumStringTag = 0x10;
+const uint32_t kLongStringTag = 0x00;
+
+// If bit 7 is clear then bit 2 indicates whether the string consists of
+// two-byte characters or one-byte characters.
+const uint32_t kStringEncodingMask = 0x4;
  const uint32_t kTwoByteStringTag = 0x0;
-const uint32_t kAsciiStringTag = 0x8;
+const uint32_t kAsciiStringTag = 0x4;

-// If bit 7 is clear, the low-order 3 bits indicate the representation
+// If bit 7 is clear, the low-order 2 bits indicate the representation
  // of the string.
-const uint32_t kStringRepresentationMask = 0x07;
+const uint32_t kStringRepresentationMask = 0x03;
  enum StringRepresentationTag {
    kSeqStringTag = 0x0,
    kConsStringTag = 0x1,
@@ -622,6 +623,7 @@
    inline bool IsOddball();
    inline bool IsSharedFunctionInfo();
    inline bool IsJSValue();
+  inline bool IsStringWrapper();
    inline bool IsProxy();
    inline bool IsBoolean();
    inline bool IsJSArray();
@@ -3116,8 +3118,8 @@
    static const int kSize = kLengthOffset + kIntSize;

    // Limits on sizes of different types of strings.
-  static const int kMaxShortStringSize = 255;
-  static const int kMaxMediumStringSize = 65535;
+  static const int kMaxShortStringSize = 63;
+  static const int kMaxMediumStringSize = 16383;

    static const int kMaxArrayIndexSize = 10;

@@ -3138,14 +3140,14 @@

    // Array index strings this short can keep their index in the hash
    // field.
-  static const int kMaxCachedArrayIndexLength = 6;
+  static const int kMaxCachedArrayIndexLength = 7;

    // Shift constants for retriving length and hash code from
    // length/hash field.
    static const int kHashShift = kNofLengthBitFields;
-  static const int kShortLengthShift = 3 * kBitsPerByte;
-  static const int kMediumLengthShift = 2 * kBitsPerByte;
-  static const int kLongLengthShift = kHashShift;
+  static const int kShortLengthShift = kHashShift + kShortStringTag;
+  static const int kMediumLengthShift = kHashShift + kMediumStringTag;
+  static const int kLongLengthShift = kHashShift + kLongStringTag;

    // Limit for truncation in short printing.
    static const int kMaxShortPrintLength = 1024;

Modified: branches/0.3/src/runtime.js
==============================================================================
--- branches/0.3/src/runtime.js (original)
+++ branches/0.3/src/runtime.js Tue Oct 28 01:56:02 2008
@@ -78,12 +78,15 @@
        // NOTE: This checks for both null and undefined.
        return (y == null) ? 0 : 1;
      } else {
+      // x is not a number, boolean, null or undefined.
+      if (y == null) return 1;  // not equal
        if (IS_OBJECT(y)) {
          return %_ObjectEquals(x, y) ? 0 : 1;
        }
        if (IS_FUNCTION(y)) {
          return %_ObjectEquals(x, y) ? 0 : 1;
        }
+
        x = %ToPrimitive(x, NO_HINT);
      }
    }

Modified: branches/0.3/src/stub-cache-arm.cc
==============================================================================
--- branches/0.3/src/stub-cache-arm.cc  (original)
+++ branches/0.3/src/stub-cache-arm.cc  Tue Oct 28 01:56:02 2008
@@ -800,19 +800,7 @@
  }


-Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name)  
{
-  UNIMPLEMENTED();
-  return Heap::undefined_value();
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) {
+Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
    UNIMPLEMENTED();
    return Heap::undefined_value();
  }

Modified: branches/0.3/src/stub-cache-ia32.cc
==============================================================================
--- branches/0.3/src/stub-cache-ia32.cc (original)
+++ branches/0.3/src/stub-cache-ia32.cc Tue Oct 28 01:56:02 2008
@@ -159,71 +159,55 @@
  }


-void StubCompiler::GenerateLoadShortStringLength(MacroAssembler* masm,
-                                                 Register receiver,
-                                                 Register scratch,
-                                                 Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
-
-  // Check that the object is a short string.
-  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
-  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
-  __ and_(scratch, kIsNotStringMask | kStringSizeMask);
-  __ cmp(scratch, kStringTag | kShortStringTag);
-  __ j(not_equal, miss_label, not_taken);
-
-  // Load length directly from the string.
-  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
-  __ shr(eax, String::kShortLengthShift);
-  __ shl(eax, kSmiTagSize);
-  __ ret(0);
-}
-
-void StubCompiler::GenerateLoadMediumStringLength(MacroAssembler* masm,
-                                                  Register receiver,
-                                                  Register scratch,
-                                                  Label* miss_label) {
-  // Check that the receiver isn't a smi.
+// Generate code to check if an object is a string.  If the object is
+// a string, the map's instance type is left in the scratch register.
+static void GenerateStringCheck(MacroAssembler* masm,
+                                Register receiver,
+                                Register scratch,
+                                Label* smi,
+                                Label* non_string_object) {
+  // Check that the object isn't a smi.
    __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
+  __ j(zero, smi, not_taken);

-  // Check that the object is a short string.
+  // Check that the object is a string.
    __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
    __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
-  __ and_(scratch, kIsNotStringMask | kStringSizeMask);
-  __ cmp(scratch, kStringTag | kMediumStringTag);
-  __ j(not_equal, miss_label, not_taken);
-
-  // Load length directly from the string.
-  __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
-  __ shr(eax, String::kMediumLengthShift);
-  __ shl(eax, kSmiTagSize);
-  __ ret(0);
+  ASSERT(kNotStringTag != 0);
+  __ test(scratch, Immediate(kNotStringTag));
+  __ j(not_zero, non_string_object, not_taken);
  }


-void StubCompiler::GenerateLoadLongStringLength(MacroAssembler* masm,
-                                                Register receiver,
-                                                Register scratch,
-                                                Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
+void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
+                                            Register receiver,
+                                            Register scratch,
+                                            Label* miss) {
+  Label load_length, check_wrapper;

-  // Check that the object is a short string.
-  __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
-  __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
-  __ and_(scratch, kIsNotStringMask | kStringSizeMask);
-  __ cmp(scratch, kStringTag | kLongStringTag);
-  __ j(not_equal, miss_label, not_taken);
+  // Check if the object is a string.
+  GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);

    // Load length directly from the string.
+  __ bind(&load_length);
+  __ and_(scratch, kStringSizeMask);
    __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
-  __ shr(eax, String::kLongLengthShift);
+  // ecx is also the receiver.
+  __ lea(ecx, Operand(scratch, String::kLongLengthShift));
+  __ shr(eax);  // ecx is implicit shift register.
    __ shl(eax, kSmiTagSize);
    __ ret(0);
+
+  // Check if the object is a JSValue wrapper.
+  __ bind(&check_wrapper);
+  __ cmp(receiver, JS_VALUE_TYPE);
+  __ j(not_equal, miss, not_taken);
+
+  // Check if the wrapped value is a string and load the length
+  // directly if it is.
+  __ mov(receiver, FieldOperand(receiver, JSValue::kValueOffset));
+  GenerateStringCheck(masm, receiver, scratch, miss, miss);
+  __ jmp(&load_length);
  }


@@ -1140,61 +1124,7 @@
  }


-Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
-  // ----------- S t a t e -------------
-  //  -- esp[0] : return address
-  //  -- esp[4] : name
-  //  -- esp[8] : receiver
-  // -----------------------------------
-  HandleScope scope;
-  Label miss;
-
-  __ mov(eax, (Operand(esp, kPointerSize)));
-  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
-  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
-
-  // Check that the name has not changed.
-  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
-  __ j(not_equal, &miss, not_taken);
-
-  GenerateLoadShortStringLength(masm(), ecx, edx, &miss);
-  __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
-  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
-  // Return the generated code.
-  return GetCode(CALLBACKS);
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadMediumStringLength(String* name)  
{
-  // ----------- S t a t e -------------
-  //  -- esp[0] : return address
-  //  -- esp[4] : name
-  //  -- esp[8] : receiver
-  // -----------------------------------
-  HandleScope scope;
-  Label miss;
-
-  __ mov(eax, (Operand(esp, kPointerSize)));
-  __ mov(ecx, (Operand(esp, 2 * kPointerSize)));
-  __ IncrementCounter(&Counters::keyed_load_string_length, 1);
-
-  // Check that the name has not changed.
-  __ cmp(Operand(eax), Immediate(Handle<String>(name)));
-  __ j(not_equal, &miss, not_taken);
-
-  GenerateLoadMediumStringLength(masm(), ecx, edx, &miss);
-  __ bind(&miss);
-  __ DecrementCounter(&Counters::keyed_load_string_length, 1);
-  GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
-
-  // Return the generated code.
-  return GetCode(CALLBACKS);
-}
-
-
-Object* KeyedLoadStubCompiler::CompileLoadLongStringLength(String* name) {
+Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
    // ----------- S t a t e -------------
    //  -- esp[0] : return address
    //  -- esp[4] : name
@@ -1211,7 +1141,7 @@
    __ cmp(Operand(eax), Immediate(Handle<String>(name)));
    __ j(not_equal, &miss, not_taken);

-  GenerateLoadLongStringLength(masm(), ecx, edx, &miss);
+  GenerateLoadStringLength(masm(), ecx, edx, &miss);
    __ bind(&miss);
    __ DecrementCounter(&Counters::keyed_load_string_length, 1);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);

Modified: branches/0.3/src/stub-cache.cc
==============================================================================
--- branches/0.3/src/stub-cache.cc      (original)
+++ branches/0.3/src/stub-cache.cc      Tue Oct 28 01:56:02 2008
@@ -263,48 +263,14 @@
  }


-Object* StubCache::ComputeKeyedLoadShortStringLength(String* name,
-                                                     String* receiver) {
+Object* StubCache::ComputeKeyedLoadStringLength(String* name,
+                                                String* receiver) {
    Code::Flags flags =
        Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
    Object* code = receiver->map()->FindInCodeCache(name, flags);
    if (code->IsUndefined()) {
      KeyedLoadStubCompiler compiler;
-    code = compiler.CompileLoadShortStringLength(name);
-    if (code->IsFailure()) return code;
-    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
-    Object* result = receiver->map()->UpdateCodeCache(name,  
Code::cast(code));
-    if (result->IsFailure()) return result;
-  }
-  return code;
-}
-
-
-Object* StubCache::ComputeKeyedLoadMediumStringLength(String* name,
-                                                      String* receiver) {
-  Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
-  Object* code = receiver->map()->FindInCodeCache(name, flags);
-  if (code->IsUndefined()) {
-    KeyedLoadStubCompiler compiler;
-    code = compiler.CompileLoadMediumStringLength(name);
-    if (code->IsFailure()) return code;
-    LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
-    Object* result = receiver->map()->UpdateCodeCache(name,  
Code::cast(code));
-    if (result->IsFailure()) return result;
-  }
-  return code;
-}
-
-
-Object* StubCache::ComputeKeyedLoadLongStringLength(String* name,
-                                                    String* receiver) {
-  Code::Flags flags =
-      Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
-  Object* code = receiver->map()->FindInCodeCache(name, flags);
-  if (code->IsUndefined()) {
-    KeyedLoadStubCompiler compiler;
-    code = compiler.CompileLoadLongStringLength(name);
+    code = compiler.CompileLoadStringLength(name);
      if (code->IsFailure()) return code;
      LOG(CodeCreateEvent("KeyedLoadIC", Code::cast(code), name));
      Object* result = receiver->map()->UpdateCodeCache(name,  
Code::cast(code));

Modified: branches/0.3/src/stub-cache.h
==============================================================================
--- branches/0.3/src/stub-cache.h       (original)
+++ branches/0.3/src/stub-cache.h       Tue Oct 28 01:56:02 2008
@@ -98,14 +98,8 @@

    static Object* ComputeKeyedLoadArrayLength(String* name, JSArray*  
receiver);

-  static Object* ComputeKeyedLoadShortStringLength(String* name,
-                                                   String* receiver);
-
-  static Object* ComputeKeyedLoadMediumStringLength(String* name,
-                                                    String* receiver);
-
-  static Object* ComputeKeyedLoadLongStringLength(String* name,
-                                                  String* receiver);
+  static Object* ComputeKeyedLoadStringLength(String* name,
+                                              String* receiver);

    static Object* ComputeKeyedLoadFunctionPrototype(String* name,
                                                     JSFunction* receiver);
@@ -341,18 +335,10 @@
                                        Register receiver,
                                        Register scratch,
                                        Label* miss_label);
-  static void GenerateLoadShortStringLength(MacroAssembler* masm,
-                                            Register receiver,
-                                            Register scratch,
-                                            Label* miss_label);
-  static void GenerateLoadMediumStringLength(MacroAssembler* masm,
-                                             Register receiver,
-                                             Register scratch,
-                                             Label* miss_label);
-  static void GenerateLoadLongStringLength(MacroAssembler* masm,
-                                           Register receiver,
-                                           Register scratch,
-                                           Label* miss_label);
+  static void GenerateLoadStringLength(MacroAssembler* masm,
+                                       Register receiver,
+                                       Register scratch,
+                                       Label* miss_label);
    static void GenerateLoadFunctionPrototype(MacroAssembler* masm,
                                              Register receiver,
                                              Register scratch1,
@@ -415,9 +401,7 @@
                                   JSObject* holder,
                                   String* name);
    Object* CompileLoadArrayLength(String* name);
-  Object* CompileLoadShortStringLength(String* name);
-  Object* CompileLoadMediumStringLength(String* name);
-  Object* CompileLoadLongStringLength(String* name);
+  Object* CompileLoadStringLength(String* name);
    Object* CompileLoadFunctionPrototype(String* name);

   private:

Modified: branches/0.3/src/top.cc
==============================================================================
--- branches/0.3/src/top.cc     (original)
+++ branches/0.3/src/top.cc     Tue Oct 28 01:56:02 2008
@@ -103,7 +103,7 @@
    clear_pending_exception();
    clear_scheduled_exception();
    thread_local_.save_context_ = NULL;
-  thread_local_.pending_external_caught_exception_ = false;
+  thread_local_.catcher_ = NULL;
  }


@@ -595,7 +595,7 @@


  Failure* Top::ReThrow(Object* exception, MessageLocation* location) {
-  // Set the exception being re-thrown.
+  // Set the exception beeing re-thrown.
    set_pending_exception(exception);
    return Failure::Exception();
  }
@@ -777,8 +777,9 @@
    // If the exception is caught externally, we store it in the
    // try/catch handler. The C code can find it later and process it if
    // necessary.
-  thread_local_.pending_external_caught_exception_ = is_caught_externally;
+  thread_local_.catcher_ = NULL;
    if (is_caught_externally) {
+    thread_local_.catcher_ = thread_local_.try_catch_handler_;
      thread_local_.try_catch_handler_->exception_ =
        reinterpret_cast<void*>(*exception_handle);
      if (!message_obj.is_null()) {
@@ -793,7 +794,7 @@
    if (report_exception) {
      if (message != NULL) {
        MessageHandler::ReportMessage(message);
-    } else {
+    } else if (!message_obj.is_null()) {
        MessageHandler::ReportMessage(location, message_obj);
      }
    }

Modified: branches/0.3/src/top.h
==============================================================================
--- branches/0.3/src/top.h      (original)
+++ branches/0.3/src/top.h      Tue Oct 28 01:56:02 2008
@@ -54,9 +54,7 @@
    bool external_caught_exception_;
    v8::TryCatch* try_catch_handler_;
    SaveContext* save_context_;
-  // Flag indicating that the try_catch_handler_ contains an exception to  
be
-  // caught.
-  bool pending_external_caught_exception_;
+  v8::TryCatch* catcher_;

    // Stack.
    Address c_entry_fp_;  // the frame pointer of the top c entry frame
@@ -160,16 +158,10 @@
      thread_local_.scheduled_exception_ = Heap::the_hole_value();
    }

-  // Propagate the external caught exception flag. If there is no external
-  // caught exception always clear the TryCatch handler as it might contain
-  // an exception object from a throw which was bypassed by a finally block
-  // doing an explicit return/break/continue.
-  static void propagate_external_caught() {
-    if (has_pending_exception()) {
-      thread_local_.external_caught_exception_ =
-          thread_local_.pending_external_caught_exception_;
-    }
-    thread_local_.pending_external_caught_exception_ = false;
+  static void setup_external_caught() {
+    thread_local_.external_caught_exception_ =
+        (thread_local_.catcher_ != NULL) &&
+        (Top::thread_local_.try_catch_handler_ ==  
Top::thread_local_.catcher_);
    }

    // Tells whether the current context has experienced an out of memory

Modified: branches/0.3/test/mjsunit/mjsunit.status
==============================================================================
--- branches/0.3/test/mjsunit/mjsunit.status    (original)
+++ branches/0.3/test/mjsunit/mjsunit.status    Tue Oct 28 01:56:02 2008
@@ -61,3 +61,7 @@
  debug-breakpoints: PASS || FAIL

  regress/regress-998565: FAIL
+
+# Bug number 130 http://code.google.com/p/v8/issues/detail?id=130
+# Fails on real ARM hardware but not on the simulator.
+string-compare-alignment: PASS || FAIL

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to