Added caching of RegExp data in compilation cache.

Added Visual Studio project file for d8 shell.

Fixed function call performance regression introduced in version 0.4.0 when splitting the global object in two parts (issue 120).

Fixed issue 131 by checking for empty handles before throwing and reporting exceptions.


git-svn-id: http://v8.googlecode.com/svn/trunk@618 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/accessors.cc b/src/accessors.cc
index cfaf44c..47d58a4 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -382,11 +382,12 @@
     // mirror for the right frame.
     const int length = frame->GetProvidedParametersCount();
     Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
+    Handle<FixedArray> array = Factory::NewFixedArray(length);
 
     // Copy the parameters to the arguments object.
-    FixedArray* array = FixedArray::cast(arguments->elements());
     ASSERT(array->length() == length);
     for (int i = 0; i < length; i++) array->set(i, frame->GetParameter(i));
+    arguments->set_elements(*array);
 
     // Return the freshly allocated arguments object.
     return *arguments;
diff --git a/src/api.cc b/src/api.cc
index 494a9d2..955a5ab 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -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();
 }
 
@@ -2193,7 +2199,7 @@
 
 
 const char* v8::V8::GetVersion() {
-  return "0.4.0";
+  return "0.4.1";
 }
 
 
diff --git a/src/builtins.cc b/src/builtins.cc
index 03bce65..9309c1c 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -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);
 }
 
 
diff --git a/src/builtins.h b/src/builtins.h
index 80a897d..bcc3e89 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -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)          \
diff --git a/src/codegen-arm.cc b/src/codegen-arm.cc
index 74f1ea7..4b1ada1 100644
--- a/src/codegen-arm.cc
+++ b/src/codegen-arm.cc
@@ -226,9 +226,7 @@
     if (FLAG_trace) {
       // Push a valid value as the parameter. The runtime call only uses
       // it as the return value to indicate non-failure.
-      __ mov(r0, Operand(Smi::FromInt(0)));
-      __ push(r0);
-      __ CallRuntime(Runtime::kTraceEnter, 1);
+      __ CallRuntime(Runtime::kTraceEnter, 0);
     }
     CheckStack();
 
@@ -242,11 +240,7 @@
       bool should_trace =
           is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
       if (should_trace) {
-        // Push a valid value as the parameter. The runtime call only uses
-        // it as the return value to indicate non-failure.
-        __ mov(r0, Operand(Smi::FromInt(0)));
-        __ push(r0);
-        __ CallRuntime(Runtime::kDebugTrace, 1);
+        __ CallRuntime(Runtime::kDebugTrace, 0);
       }
 #endif
       VisitStatements(body);
@@ -1846,8 +1840,8 @@
 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
   Comment cmnt(masm_, "[ DebuggerStatament");
   if (FLAG_debug_info) RecordStatementPosition(node);
-  __ CallRuntime(Runtime::kDebugBreak, 1);
-  __ push(r0);
+  __ CallRuntime(Runtime::kDebugBreak, 0);
+  // Ignore the return value.
 }
 
 
@@ -2246,9 +2240,10 @@
     __ mov(r0, Operand(var->name()));
     __ push(r0);
 
-    // TODO(120): use JSGlobalObject for function lookup and inline cache,
-    // and use global proxy as 'this' for invocation.
-    LoadGlobalReceiver(r0);
+    // Pass the global object as the receiver and let the IC stub
+    // patch the stack to use the global proxy as 'this' in the
+    // invoked function.
+    LoadGlobal();
 
     // Load the arguments.
     for (int i = 0; i < args->length(); i++) Load(args->at(i));
@@ -2335,11 +2330,10 @@
 
     // Load the function.
     Load(function);
-    // Pass the global object as the receiver.
 
-    // TODO(120): use JSGlobalObject for function lookup and inline cache,
-    // and use global proxy as 'this' for invocation.
+    // Pass the global proxy as the receiver.
     LoadGlobalReceiver(r0);
+
     // Call the function.
     CallWithArguments(args, node->position());
     __ push(r0);
@@ -2357,9 +2351,10 @@
   // evaluated.
 
   // Compute function to call and use the global object as the
-  // receiver.
+  // receiver. There is no need to use the global proxy here because
+  // it will always be replaced with a newly allocated object.
   Load(node->expression());
-  LoadGlobalReceiver(r0);
+  LoadGlobal();
 
   // Push the arguments ("left-to-right") on the stack.
   ZoneList<Expression*>* args = node->arguments();
diff --git a/src/codegen-ia32.cc b/src/codegen-ia32.cc
index a339a96..2765587 100644
--- a/src/codegen-ia32.cc
+++ b/src/codegen-ia32.cc
@@ -356,8 +356,8 @@
     }
 
     if (FLAG_trace) {
-      __ CallRuntime(Runtime::kTraceEnter, 1);
-      frame_->Push(eax);
+      __ CallRuntime(Runtime::kTraceEnter, 0);
+      // Ignore the return value.
     }
     CheckStack();
 
@@ -371,8 +371,8 @@
       bool should_trace =
           is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls;
       if (should_trace) {
-        __ CallRuntime(Runtime::kDebugTrace, 1);
-        frame_->Push(eax);
+        __ CallRuntime(Runtime::kDebugTrace, 0);
+        // Ignore the return value.
       }
 #endif
       VisitStatements(body);
@@ -2218,8 +2218,8 @@
 void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
   Comment cmnt(masm_, "[ DebuggerStatement");
   RecordStatementPosition(node);
-  __ CallRuntime(Runtime::kDebugBreak, 1);
-  frame_->Push(eax);
+  __ CallRuntime(Runtime::kDebugBreak, 0);
+  // Ignore the return value.
 }
 
 
@@ -2660,9 +2660,10 @@
     // Push the name of the function and the receiver onto the stack.
     frame_->Push(Immediate(var->name()));
 
-    // TODO(120): use JSGlobalObject for function lookup and inline cache,
-    // and use global proxy as 'this' for invocation.
-    LoadGlobalReceiver(eax);
+    // Pass the global object as the receiver and let the IC stub
+    // patch the stack to use the global proxy as 'this' in the
+    // invoked function.
+    LoadGlobal();
 
     // Load the arguments.
     for (int i = 0; i < args->length(); i++) {
@@ -2747,10 +2748,7 @@
     // Load the function.
     Load(function);
 
-    // Pass the global object as the receiver.
-
-    // TODO(120): use JSGlobalObject for function lookup and inline cache,
-    // and use global proxy as 'this' for invocation.
+    // Pass the global proxy as the receiver.
     LoadGlobalReceiver(eax);
 
     // Call the function.
@@ -2769,9 +2767,10 @@
   // evaluated.
 
   // Compute function to call and use the global object as the
-  // receiver.
+  // receiver. There is no need to use the global proxy here because
+  // it will always be replaced with a newly allocated object.
   Load(node->expression());
-  LoadGlobalReceiver(eax);
+  LoadGlobal();
 
   // Push the arguments ("left-to-right") on the stack.
   ZoneList<Expression*>* args = node->arguments();
@@ -2851,38 +2850,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.
@@ -2891,11 +2878,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.
@@ -2915,11 +2902,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.
@@ -2928,7 +2914,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.
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index 48b2870..bf32621 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -32,7 +32,7 @@
 namespace v8 { namespace internal {
 
 enum {
-  NUMBER_OF_ENTRY_KINDS = CompilationCache::EVAL_CONTEXTUAL + 1
+  NUMBER_OF_ENTRY_KINDS = CompilationCache::LAST_ENTRY + 1
 };
 
 
@@ -132,9 +132,9 @@
 }
 
 
-void CompilationCache::Associate(Handle<String> source,
-                                 Entry entry,
-                                 Handle<JSFunction> boilerplate) {
+void CompilationCache::PutFunction(Handle<String> source,
+                                   Entry entry,
+                                   Handle<JSFunction> boilerplate) {
   HandleScope scope;
   ASSERT(boilerplate->IsBoilerplate());
   Handle<CompilationCacheTable> table = GetTable(entry);
@@ -142,6 +142,29 @@
 }
 
 
+Handle<FixedArray> CompilationCache::LookupRegExp(Handle<String> source,
+                                                  JSRegExp::Flags flags) {
+  Handle<CompilationCacheTable> table = GetTable(REGEXP);
+  Object* result = table->LookupRegExp(*source, flags);
+  if (result->IsFixedArray()) {
+    Counters::regexp_cache_hits.Increment();
+    return Handle<FixedArray>(FixedArray::cast(result));
+  } else {
+    Counters::regexp_cache_misses.Increment();
+    return Handle<FixedArray>();
+  }
+}
+
+
+void CompilationCache::PutRegExp(Handle<String> source,
+                                 JSRegExp::Flags flags,
+                                 Handle<FixedArray> data) {
+  HandleScope scope;
+  Handle<CompilationCacheTable> table = GetTable(REGEXP);
+  CALL_HEAP_FUNCTION_VOID(table->PutRegExp(*source, flags, *data));
+}
+
+
 void CompilationCache::Clear() {
   for (int i = 0; i < NUMBER_OF_ENTRY_KINDS; i++) {
     tables[i] = Heap::undefined_value();
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index a87c495..abe6110 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -42,7 +42,9 @@
   enum Entry {
     SCRIPT,
     EVAL_GLOBAL,
-    EVAL_CONTEXTUAL
+    EVAL_CONTEXTUAL,
+    REGEXP,
+    LAST_ENTRY = REGEXP
   };
 
   // Finds the script function boilerplate for a source
@@ -59,11 +61,22 @@
   static Handle<JSFunction> LookupEval(Handle<String> source,
                                        Entry entry);
 
+  // Returns the regexp data associated with the given regexp if it
+  // is in cache, otherwise an empty handle.
+  static Handle<FixedArray> LookupRegExp(Handle<String> source,
+                                         JSRegExp::Flags flags);
+
+  // Associate the (source, flags) pair to the given regexp data.
+  // This may overwrite an existing mapping.
+  static void PutRegExp(Handle<String> source,
+                        JSRegExp::Flags flags,
+                        Handle<FixedArray> data);
+
   // Associate the (source, kind) pair to the boilerplate. This may
   // overwrite an existing mapping.
-  static void Associate(Handle<String> source,
-                        Entry entry,
-                        Handle<JSFunction> boilerplate);
+  static void PutFunction(Handle<String> source,
+                          Entry entry,
+                          Handle<JSFunction> boilerplate);
 
   // Clear the cache - also used to initialize the cache at startup.
   static void Clear();
diff --git a/src/compiler.cc b/src/compiler.cc
index 999cf4c..11ac145 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -189,7 +189,7 @@
     // Compile the function and add it to the cache.
     result = MakeFunction(true, false, script, extension, pre_data);
     if (extension == NULL && !result.is_null()) {
-      CompilationCache::Associate(source, CompilationCache::SCRIPT, result);
+      CompilationCache::PutFunction(source, CompilationCache::SCRIPT, result);
     }
 
     // Get rid of the pre-parsing data (if necessary).
@@ -223,7 +223,7 @@
     script->set_line_offset(Smi::FromInt(line_offset));
     result = MakeFunction(is_global, true, script, NULL, NULL);
     if (!result.is_null()) {
-      CompilationCache::Associate(source, entry, result);
+      CompilationCache::PutFunction(source, entry, result);
     }
   }
   return result;
diff --git a/src/contexts.cc b/src/contexts.cc
index 81ad8d2..6aaa4cc 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -27,6 +27,7 @@
 
 #include "v8.h"
 
+#include "bootstrapper.h"
 #include "debug.h"
 #include "scopeinfo.h"
 
@@ -99,19 +100,19 @@
     }
 
     // check extension/with object
-    Handle<JSObject> context_ext(context->extension());
-    if (*context_ext != NULL) {
+    if (context->has_extension()) {
+      Handle<JSObject> extension = Handle<JSObject>(context->extension());
       if ((flags & FOLLOW_PROTOTYPE_CHAIN) == 0) {
-        *attributes = context_ext->GetLocalPropertyAttribute(*name);
+        *attributes = extension->GetLocalPropertyAttribute(*name);
       } else {
-        *attributes = context_ext->GetPropertyAttribute(*name);
+        *attributes = extension->GetPropertyAttribute(*name);
       }
       if (*attributes != ABSENT) {
         // property found
         if (FLAG_trace_contexts) {
-          PrintF("=> found property in context object %p\n", *context_ext);
+          PrintF("=> found property in context object %p\n", *extension);
         }
-        return context_ext;
+        return extension;
       }
     }
 
@@ -184,11 +185,10 @@
     // proceed with enclosing context
     if (context->IsGlobalContext()) {
       follow_context_chain = false;
-    } else if (context->previous() != NULL) {
-      context = Handle<Context>(context->previous());
-    } else {
-      ASSERT(context->is_function_context());
+    } else if (context->is_function_context()) {
       context = Handle<Context>(Context::cast(context->closure()->context()));
+    } else {
+      context = Handle<Context>(context->previous());
     }
   } while (follow_context_chain);
 
@@ -196,8 +196,23 @@
   if (FLAG_trace_contexts) {
     PrintF("=> no property/slot found\n");
   }
-  return Handle<Object>(reinterpret_cast<JSObject*>(NULL));
+  return Handle<Object>::null();
 }
 
 
+#ifdef DEBUG
+bool Context::IsBootstrappingOrContext(Object* object) {
+  // During bootstrapping we allow all objects to pass as
+  // contexts. This is necessary to fix circular dependencies.
+  return Bootstrapper::IsActive() || object->IsContext();
+}
+
+
+bool Context::IsBootstrappingOrGlobalObject(Object* object) {
+  // During bootstrapping we allow all objects to pass as global
+  // objects. This is necessary to fix circular dependencies.
+  return Bootstrapper::IsActive() || object->IsGlobalObject();
+}
+#endif
+
 } }  // namespace v8::internal
diff --git a/src/contexts.h b/src/contexts.h
index 2e6c39a..30aa5bb 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -220,23 +220,24 @@
   JSFunction* closure() { return JSFunction::cast(get(CLOSURE_INDEX)); }
   void set_closure(JSFunction* closure) { set(CLOSURE_INDEX, closure); }
 
-  Context* fcontext() {
-    return reinterpret_cast<Context*>(get(FCONTEXT_INDEX));
-  }
+  Context* fcontext() { return Context::cast(get(FCONTEXT_INDEX)); }
   void set_fcontext(Context* context) { set(FCONTEXT_INDEX, context); }
 
   Context* previous() {
-    return reinterpret_cast<Context*>(get(PREVIOUS_INDEX));
+    Object* result = unchecked_previous();
+    ASSERT(IsBootstrappingOrContext(result));
+    return reinterpret_cast<Context*>(result);
   }
   void set_previous(Context* context) { set(PREVIOUS_INDEX, context); }
 
-  JSObject* extension() {
-    return reinterpret_cast<JSObject*>(get(EXTENSION_INDEX));
-  }
+  bool has_extension() { return unchecked_extension() != NULL; }
+  JSObject* extension() { return JSObject::cast(unchecked_extension()); }
   void set_extension(JSObject* object) { set(EXTENSION_INDEX, object); }
 
   GlobalObject* global() {
-    return reinterpret_cast<GlobalObject*>(get(GLOBAL_INDEX));
+    Object* result = get(GLOBAL_INDEX);
+    ASSERT(IsBootstrappingOrGlobalObject(result));
+    return reinterpret_cast<GlobalObject*>(result);
   }
   void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); }
 
@@ -251,7 +252,7 @@
   Context* global_context();
 
   // Tells if this is a function context (as opposed to a 'with' context).
-  bool is_function_context() { return previous() == NULL; }
+  bool is_function_context() { return unchecked_previous() == NULL; }
 
   // Tells whether the global context is marked with out of memory.
   bool has_out_of_memory() {
@@ -293,7 +294,7 @@
   //    and the name is the property name, and the property exists.
   //    attributes != ABSENT.
   //
-  // 4) index_ < 0 && result.deref() == NULL:
+  // 4) index_ < 0 && result.is_null():
   //    there was no context found with the corresponding property.
   //    attributes == ABSENT.
   Handle<Object> Lookup(Handle<String> name, ContextLookupFlags flags,
@@ -303,6 +304,17 @@
   static int SlotOffset(int index) {
     return kHeaderSize + index * kPointerSize - kHeapObjectTag;
   }
+
+ private:
+  // Unchecked access to the slots.
+  Object* unchecked_previous() { return get(PREVIOUS_INDEX); }
+  Object* unchecked_extension() { return get(EXTENSION_INDEX); }
+
+#ifdef DEBUG
+  // Bootstrapping-aware type checks.
+  static bool IsBootstrappingOrContext(Object* object);
+  static bool IsBootstrappingOrGlobalObject(Object* object);
+#endif
 };
 
 } }  // namespace v8::internal
diff --git a/src/factory.cc b/src/factory.cc
index 4e5f5da..55af33d 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -524,7 +524,7 @@
     Handle<String> key =
         SymbolFromString(Handle<String>(String::cast(entry->name())));
     // Check if a descriptor with this name already exists before writing.
-    if (result->BinarySearch(*key, 0, descriptor_count - 1) ==
+    if (result->LinearSearch(*key, descriptor_count) ==
         DescriptorArray::kNotFound) {
       CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
       w.Write(&desc);
@@ -685,7 +685,7 @@
   }
 
   int instance_size = kPointerSize * internal_field_count;
-  InstanceType type = JS_OBJECT_TYPE;  // initialize to a valid value
+  InstanceType type = INVALID_TYPE;
   switch (instance_type) {
     case JavaScriptObject:
       type = JS_OBJECT_TYPE;
@@ -700,9 +700,9 @@
       instance_size += JSGlobalProxy::kSize;
       break;
     default:
-      ASSERT(false);
       break;
   }
+  ASSERT(type != INVALID_TYPE);
 
   Handle<JSFunction> result =
       Factory::NewFunction(Factory::empty_symbol(), type, instance_size,
@@ -808,6 +808,20 @@
 }
 
 
+void Factory::SetRegExpData(Handle<JSRegExp> regexp,
+                            JSRegExp::Type type,
+                            Handle<String> source,
+                            JSRegExp::Flags flags,
+                            Handle<Object> data) {
+  Handle<FixedArray> store = NewFixedArray(JSRegExp::kDataSize);
+  store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
+  store->set(JSRegExp::kSourceIndex, *source);
+  store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
+  store->set(JSRegExp::kAtomPatternIndex, *data);
+  regexp->set_data(*store);
+}
+
+
 void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
                                 Handle<JSObject> instance,
                                 bool* pending_exception) {
diff --git a/src/factory.h b/src/factory.h
index 42de71c..bb04b6b 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -308,6 +308,14 @@
   static Handle<Map> ObjectLiteralMapFromCache(Handle<Context> context,
                                                Handle<FixedArray> keys);
 
+  // Creates a new FixedArray that holds the data associated with the
+  // regexp and stores it in the regexp.
+  static void SetRegExpData(Handle<JSRegExp> regexp,
+                            JSRegExp::Type type,
+                            Handle<String> source,
+                            JSRegExp::Flags flags,
+                            Handle<Object> data);
+
  private:
   static Handle<JSFunction> NewFunctionHelper(Handle<String> name,
                                               Handle<Object> prototype);
diff --git a/src/heap.cc b/src/heap.cc
index 00cf78b..14c1940 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1378,12 +1378,11 @@
 
   Object* result = Allocate(map, NEW_SPACE);
   if (result->IsFailure()) return result;
-
+  ASSERT(InNewSpace(result));
   ConsString* cons_string = ConsString::cast(result);
-  cons_string->set_first(first);
-  cons_string->set_second(second);
+  cons_string->set_first(first, SKIP_WRITE_BARRIER);
+  cons_string->set_second(second, SKIP_WRITE_BARRIER);
   cons_string->set_length(length);
-
   return result;
 }
 
@@ -1615,7 +1614,7 @@
   function->set_shared(shared);
   function->set_prototype_or_initial_map(prototype);
   function->set_context(undefined_value());
-  function->set_literals(empty_fixed_array());
+  function->set_literals(empty_fixed_array(), SKIP_WRITE_BARRIER);
   return function;
 }
 
@@ -1676,14 +1675,6 @@
                                                 Smi::FromInt(length),
                                                 SKIP_WRITE_BARRIER);
 
-  // Allocate the elements if needed.
-  if (length > 0) {
-    // Allocate the fixed array.
-    Object* obj = Heap::AllocateFixedArray(length);
-    if (obj->IsFailure()) return obj;
-    JSObject::cast(result)->set_elements(FixedArray::cast(obj));
-  }
-
   // Check the state of the object
   ASSERT(JSObject::cast(result)->HasFastProperties());
   ASSERT(JSObject::cast(result)->HasFastElements());
@@ -1945,17 +1936,17 @@
   }
 
   if (map == short_sliced_string_map()) return short_sliced_symbol_map();
-  if (map == medium_sliced_string_map()) return short_sliced_symbol_map();
-  if (map == long_sliced_string_map()) return short_sliced_symbol_map();
+  if (map == medium_sliced_string_map()) return medium_sliced_symbol_map();
+  if (map == long_sliced_string_map()) return long_sliced_symbol_map();
 
   if (map == short_sliced_ascii_string_map()) {
     return short_sliced_ascii_symbol_map();
   }
   if (map == medium_sliced_ascii_string_map()) {
-    return short_sliced_ascii_symbol_map();
+    return medium_sliced_ascii_symbol_map();
   }
   if (map == long_sliced_ascii_string_map()) {
-    return short_sliced_ascii_symbol_map();
+    return long_sliced_ascii_symbol_map();
   }
 
   if (map == short_external_string_map()) return short_external_string_map();
diff --git a/src/heap.h b/src/heap.h
index c619e9f..87b972d 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -741,6 +741,9 @@
     return amount_of_external_allocated_memory_;
   }
 
+  // Allocate unitialized fixed array (pretenure == NON_TENURE).
+  static Object* AllocateRawFixedArray(int length);
+
  private:
   static int semispace_size_;
   static int initial_semispace_size_;
@@ -835,9 +838,6 @@
   // (since both AllocateRaw and AllocateRawMap are inlined).
   static inline Object* AllocateRawMap(int size_in_bytes);
 
-  // Allocate unitialized fixed array (pretenure == NON_TENURE).
-  static Object* AllocateRawFixedArray(int length);
-
   // Initializes a JSObject based on its map.
   static void InitializeJSObjectFromMap(JSObject* obj,
                                         FixedArray* properties,
diff --git a/src/ic-arm.cc b/src/ic-arm.cc
index d08e7b7..bdb3b76 100644
--- a/src/ic-arm.cc
+++ b/src/ic-arm.cc
@@ -44,8 +44,7 @@
 
 // Helper function used from LoadIC/CallIC GenerateNormal.
 static void GenerateDictionaryLoad(MacroAssembler* masm,
-                                   Label* done_label,
-                                   Label* miss_label,
+                                   Label* miss,
                                    Register t0,
                                    Register t1) {
   // Register use:
@@ -61,6 +60,8 @@
   //
   // r2 - holds the name of the property and is unchanges.
 
+  Label done;
+
   // Check for the absence of an interceptor.
   // Load the map into t0.
   __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset));
@@ -68,14 +69,14 @@
   __ ldr(t0, FieldMemOperand(t1, Map::kInstanceAttributesOffset));
   __ tst(t0, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8))));
   // Jump to miss if the interceptor bit is set.
-  __ b(ne, miss_label);
+  __ b(ne, miss);
 
 
   // Check that the properties array is a dictionary.
   __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset));
   __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset));
   __ cmp(r3, Operand(Factory::hash_table_map()));
-  __ b(ne, miss_label);
+  __ b(ne, miss);
 
   // Compute the capacity mask.
   const int kCapacityOffset =
@@ -107,17 +108,17 @@
     __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset));
     __ cmp(r2, Operand(ip));
     if (i != kProbes - 1) {
-      __ b(eq, done_label);
+      __ b(eq, &done);
     } else {
-      __ b(ne, miss_label);
+      __ b(ne, miss);
     }
   }
 
   // Check that the value is a normal property.
-  __ bind(done_label);  // t1 == t0 + 4*index
+  __ bind(&done);  // t1 == t0 + 4*index
   __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize));
   __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
-  __ b(ne, miss_label);
+  __ b(ne, miss);
 
   // Get the value at the masked, scaled index and return.
   __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize));
@@ -156,103 +157,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);
@@ -340,12 +299,42 @@
 }
 
 
+static void GenerateNormalHelper(MacroAssembler* masm,
+                                 int argc,
+                                 bool is_global_object,
+                                 Label* miss) {
+  // Search dictionary - put result in register r1.
+  GenerateDictionaryLoad(masm, miss, r0, r1);
+
+  // Check that the value isn't a smi.
+  __ tst(r1, Operand(kSmiTagMask));
+  __ b(eq, miss);
+
+  // Check that the value is a JSFunction.
+  __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
+  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
+  __ cmp(r0, Operand(JS_FUNCTION_TYPE));
+  __ b(ne, miss);
+
+  // Patch the receiver with the global proxy if necessary.
+  if (is_global_object) {
+    __ ldr(r2, MemOperand(sp, argc * kPointerSize));
+    __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
+    __ str(r2, MemOperand(sp, argc * kPointerSize));
+  }
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
+}
+
+
 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
   // ----------- S t a t e -------------
   //  -- lr: return address
   // -----------------------------------
 
-  Label miss, probe, done, global;
+  Label miss, global_object, non_global_object;
 
   // Get the receiver of the function from the stack into r1.
   __ ldr(r1, MemOperand(sp, argc * kPointerSize));
@@ -365,35 +354,28 @@
   // If this assert fails, we have to check upper bound too.
   ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
 
-  // Check for access to global object (unlikely).
+  // Check for access to global object.
+  __ cmp(r0, Operand(JS_GLOBAL_OBJECT_TYPE));
+  __ b(eq, &global_object);
+  __ cmp(r0, Operand(JS_BUILTINS_OBJECT_TYPE));
+  __ b(ne, &non_global_object);
+
+  // Accessing global object: Load and invoke.
+  __ bind(&global_object);
+  GenerateNormalHelper(masm, argc, true, &miss);
+
+  // Accessing non-global object: Check for access to global proxy.
+  Label global_proxy, invoke;
+  __ bind(&non_global_object);
   __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE));
-  __ b(eq, &global);
-
-  // Search the dictionary placing the result in r1.
-  __ bind(&probe);
-  GenerateDictionaryLoad(masm, &done, &miss, r0, r1);
-
-  // Check that the value isn't a smi.
-  __ tst(r1, Operand(kSmiTagMask));
-  __ b(eq, &miss);
-
-  // Check that the value is a JSFunction.
-  __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
-  __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
-  __ cmp(r0, Operand(JS_FUNCTION_TYPE));
-  __ b(ne, &miss);
-
-  // Patch the function on the stack; 1 ~ receiver.
-  __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
-
-  // Invoke the function.
-  ParameterCount actual(argc);
-  __ InvokeFunction(r1, actual, JUMP_FUNCTION);
+  __ b(eq, &global_proxy);
+  __ bind(&invoke);
+  GenerateNormalHelper(masm, argc, false, &miss);
 
   // Global object access: Check access rights.
-  __ bind(&global);
+  __ bind(&global_proxy);
   __ CheckAccessGlobalProxy(r1, r0, &miss);
-  __ b(&probe);
+  __ b(&invoke);
 
   // Cache miss: Jump to runtime.
   __ bind(&miss);
@@ -425,16 +407,30 @@
   CEntryStub stub;
   __ CallStub(&stub);
 
-  // Move result to r1.
+  // Move result to r1 and leave the internal frame.
   __ mov(r1, Operand(r0));
-
   __ LeaveInternalFrame();
 
-  // Patch the function on the stack; 1 ~ receiver.
-  __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
+  // Check if the receiver is a global object of some sort.
+  Label invoke, global;
+  __ ldr(r2, MemOperand(sp, argc * kPointerSize));  // receiver
+  __ tst(r2, Operand(kSmiTagMask));
+  __ b(eq, &invoke);
+  __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
+  __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE));
+  __ b(eq, &global);
+  __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
+  __ b(ne, &invoke);
+
+  // Patch the receiver on the stack.
+  __ bind(&global);
+  __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
+  __ str(r2, MemOperand(sp, argc * kPointerSize));
 
   // Invoke the function.
   ParameterCount actual(argc);
+  __ bind(&invoke);
   __ InvokeFunction(r1, actual, JUMP_FUNCTION);
 }
 
@@ -466,7 +462,7 @@
   //  -- [sp]  : receiver
   // -----------------------------------
 
-  Label miss, probe, done, global;
+  Label miss, probe, global;
 
   __ ldr(r0, MemOperand(sp, 0));
   // Check that the receiver isn't a smi.
@@ -485,9 +481,8 @@
   __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE));
   __ b(eq, &global);
 
-
   __ bind(&probe);
-  GenerateDictionaryLoad(masm, &done, &miss, r1, r0);
+  GenerateDictionaryLoad(masm, &miss, r1, r0);
   __ Ret();
 
   // Global object access: Check access rights.
diff --git a/src/ic-ia32.cc b/src/ic-ia32.cc
index d5fe47d..82eb14d 100644
--- a/src/ic-ia32.cc
+++ b/src/ic-ia32.cc
@@ -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);
 }
@@ -206,6 +172,18 @@
 }
 
 
+#ifdef DEBUG
+// For use in assert below.
+static int TenToThe(int exponent) {
+  ASSERT(exponent <= 9);
+  ASSERT(exponent >= 1);
+  int answer = 10;
+  for (int i = 1; i < exponent; i++) answer *= 10;
+  return answer;
+}
+#endif
+
+
 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
   // ----------- S t a t e -------------
   //  -- esp[0] : return address
@@ -262,6 +240,11 @@
   __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
   __ ret(0);
   // Array index string: If short enough use cache in length/hash field (ebx).
+  // We assert that there are enough bits in an int32_t after the hash shift
+  // bits have been subtracted to allow space for the length and the cached
+  // array index.
+  ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
+             (1 << (String::kShortLengthShift - String::kHashShift)));
   __ bind(&index_string);
   const int kLengthFieldLimit =
       (String::kMaxCachedArrayIndexLength + 1) << String::kShortLengthShift;
@@ -455,11 +438,42 @@
 }
 
 
+static void GenerateNormalHelper(MacroAssembler* masm,
+                                 int argc,
+                                 bool is_global_object,
+                                 Label* miss) {
+  // Search dictionary - put result in register edx.
+  GenerateDictionaryLoad(masm, miss, eax, edx, ebx, ecx);
+
+  // Move the result to register edi and check that it isn't a smi.
+  __ mov(edi, Operand(edx));
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, miss, not_taken);
+
+  // Check that the value is a JavaScript function.
+  __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
+  __ cmp(edx, JS_FUNCTION_TYPE);
+  __ j(not_equal, miss, not_taken);
+
+  // Patch the receiver with the global proxy if necessary.
+  if (is_global_object) {
+    __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
+  // Invoke the function.
+  ParameterCount actual(argc);
+  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
+}
+
+
 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
   // ----------- S t a t e -------------
   // -----------------------------------
 
-  Label miss, probe, global;
+  Label miss, global_object, non_global_object;
 
   // Get the receiver of the function from the stack; 1 ~ return address.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
@@ -480,32 +494,27 @@
   ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
 
   // Check for access to global object.
+  __ cmp(eax, JS_GLOBAL_OBJECT_TYPE);
+  __ j(equal, &global_object);
+  __ cmp(eax, JS_BUILTINS_OBJECT_TYPE);
+  __ j(not_equal, &non_global_object);
+
+  // Accessing global object: Load and invoke.
+  __ bind(&global_object);
+  GenerateNormalHelper(masm, argc, true, &miss);
+
+  // Accessing non-global object: Check for access to global proxy.
+  Label global_proxy, invoke;
+  __ bind(&non_global_object);
   __ cmp(eax, JS_GLOBAL_PROXY_TYPE);
-  __ j(equal, &global, not_taken);
+  __ j(equal, &global_proxy, not_taken);
+  __ bind(&invoke);
+  GenerateNormalHelper(masm, argc, false, &miss);
 
-  // Search the dictionary placing the result in edx.
-  __ bind(&probe);
-  GenerateDictionaryLoad(masm, &miss, eax, edx, ebx, ecx);
-
-  // Move the result to register edi and check that it isn't a smi.
-  __ mov(edi, Operand(edx));
-  __ test(edx, Immediate(kSmiTagMask));
-  __ j(zero, &miss, not_taken);
-
-  // Check that the value is a JavaScript function.
-  __ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
-  __ movzx_b(edx, FieldOperand(edx, Map::kInstanceTypeOffset));
-  __ cmp(edx, JS_FUNCTION_TYPE);
-  __ j(not_equal, &miss, not_taken);
-
-  // Invoke the function.
-  ParameterCount actual(argc);
-  __ InvokeFunction(edi, actual, JUMP_FUNCTION);
-
-  // Global object access: Check access rights.
-  __ bind(&global);
+  // Global object proxy access: Check access rights.
+  __ bind(&global_proxy);
   __ CheckAccessGlobalProxy(edx, eax, &miss);
-  __ jmp(&probe);
+  __ jmp(&invoke);
 
   // Cache miss: Jump to runtime.
   __ bind(&miss);
@@ -542,8 +551,26 @@
   __ mov(Operand(edi), eax);
   __ LeaveInternalFrame();
 
+  // Check if the receiver is a global object of some sort.
+  Label invoke, global;
+  __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));  // receiver
+  __ test(edx, Immediate(kSmiTagMask));
+  __ j(zero, &invoke, not_taken);
+  __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
+  __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
+  __ cmp(ecx, JS_GLOBAL_OBJECT_TYPE);
+  __ j(equal, &global);
+  __ cmp(ecx, JS_BUILTINS_OBJECT_TYPE);
+  __ j(not_equal, &invoke);
+
+  // Patch the receiver on the stack.
+  __ bind(&global);
+  __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+  __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+
   // Invoke the function.
   ParameterCount actual(argc);
+  __ bind(&invoke);
   __ InvokeFunction(edi, actual, JUMP_FUNCTION);
 }
 
diff --git a/src/ic.cc b/src/ic.cc
index 9d954bb..2ec7b09 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -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
diff --git a/src/ic.h b/src/ic.h
index fd5c72b..d32edaa 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -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:
diff --git a/src/jsregexp.cc b/src/jsregexp.cc
index 675f82a..02b53e0 100644
--- a/src/jsregexp.cc
+++ b/src/jsregexp.cc
@@ -30,10 +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 {
 
@@ -143,29 +153,59 @@
 }
 
 
+static JSRegExp::Flags RegExpFlagsFromString(Handle<String> str) {
+  int flags = JSRegExp::NONE;
+  for (int i = 0; i < str->length(); i++) {
+    switch (str->Get(i)) {
+      case 'i':
+        flags |= JSRegExp::IGNORE_CASE;
+        break;
+      case 'g':
+        flags |= JSRegExp::GLOBAL;
+        break;
+      case 'm':
+        flags |= JSRegExp::MULTILINE;
+        break;
+    }
+  }
+  return JSRegExp::Flags(flags);
+}
+
+
 unibrow::Predicate<unibrow::RegExpSpecialChar, 128> is_reg_exp_special_char;
 
 
 Handle<Object> RegExpImpl::Compile(Handle<JSRegExp> re,
                                    Handle<String> pattern,
-                                   Handle<String> flags) {
-  bool is_atom = true;
-  for (int i = 0; is_atom && i < flags->length(); i++) {
-    if (flags->Get(i) == 'i')
-      is_atom = false;
-  }
-  for (int i = 0; is_atom && i < pattern->length(); i++) {
-    if (is_reg_exp_special_char.get(pattern->Get(i)))
-      is_atom = false;
-  }
+                                   Handle<String> flag_str) {
+  JSRegExp::Flags flags = RegExpFlagsFromString(flag_str);
+  Handle<FixedArray> cached = CompilationCache::LookupRegExp(pattern, flags);
+  bool in_cache = !cached.is_null();
   Handle<Object> result;
-  if (is_atom) {
-    result = AtomCompile(re, pattern);
+  if (in_cache) {
+    re->set_data(*cached);
+    result = re;
   } else {
-    result = JsreCompile(re, pattern, flags);
+    bool is_atom = !flags.is_ignore_case();
+    for (int i = 0; is_atom && i < pattern->length(); i++) {
+      if (is_reg_exp_special_char.get(pattern->Get(i)))
+        is_atom = false;
+    }
+    if (is_atom) {
+      result = AtomCompile(re, pattern, flags);
+    } else {
+      result = JsreCompile(re, pattern, flags);
+    }
+    Object* data = re->data();
+    if (data->IsFixedArray()) {
+      // If compilation succeeded then the data is set on the regexp
+      // and we can store it in the cache.
+      Handle<FixedArray> data(FixedArray::cast(re->data()));
+      CompilationCache::PutRegExp(pattern, flags, data);
+    }
   }
 
-  LOG(RegExpCompileEvent(re));
+  LOG(RegExpCompileEvent(re, in_cache));
   return result;
 }
 
@@ -173,7 +213,7 @@
 Handle<Object> RegExpImpl::Exec(Handle<JSRegExp> regexp,
                                 Handle<String> subject,
                                 Handle<Object> index) {
-  switch (regexp->type_tag()) {
+  switch (regexp->TypeTag()) {
     case JSRegExp::JSCRE:
       return JsreExec(regexp, subject, index);
     case JSRegExp::ATOM:
@@ -187,7 +227,7 @@
 
 Handle<Object> RegExpImpl::ExecGlobal(Handle<JSRegExp> regexp,
                                 Handle<String> subject) {
-  switch (regexp->type_tag()) {
+  switch (regexp->TypeTag()) {
     case JSRegExp::JSCRE:
       return JsreExecGlobal(regexp, subject);
     case JSRegExp::ATOM:
@@ -200,9 +240,9 @@
 
 
 Handle<Object> RegExpImpl::AtomCompile(Handle<JSRegExp> re,
-                                       Handle<String> pattern) {
-  re->set_type_tag(JSRegExp::ATOM);
-  re->set_data(*pattern);
+                                       Handle<String> pattern,
+                                       JSRegExp::Flags flags) {
+  Factory::SetRegExpData(re, JSRegExp::ATOM, pattern, flags, pattern);
   return re;
 }
 
@@ -210,7 +250,7 @@
 Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
                                     Handle<String> subject,
                                     Handle<Object> index) {
-  Handle<String> needle(String::cast(re->data()));
+  Handle<String> needle(String::cast(re->DataAt(JSRegExp::kAtomPatternIndex)));
 
   uint32_t start_index;
   if (!Array::IndexFromObject(*index, &start_index)) {
@@ -234,7 +274,7 @@
 
 Handle<Object> RegExpImpl::AtomExecGlobal(Handle<JSRegExp> re,
                                           Handle<String> subject) {
-  Handle<String> needle(String::cast(re->data()));
+  Handle<String> needle(String::cast(re->DataAt(JSRegExp::kAtomPatternIndex)));
   Handle<JSArray> result = Factory::NewJSArray(1);
   int index = 0;
   int match_count = 0;
@@ -269,14 +309,13 @@
 
 Handle<Object> RegExpImpl::JsreCompile(Handle<JSRegExp> re,
                                        Handle<String> pattern,
-                                       Handle<String> flags) {
-  JSRegExpIgnoreCaseOption case_option = JSRegExpDoNotIgnoreCase;
-  JSRegExpMultilineOption multiline_option = JSRegExpSingleLine;
-  FlattenString(flags);
-  for (int i = 0; i < flags->length(); i++) {
-    if (flags->Get(i) == 'i') case_option = JSRegExpIgnoreCase;
-    if (flags->Get(i) == 'm') multiline_option = JSRegExpMultiline;
-  }
+                                       JSRegExp::Flags flags) {
+  JSRegExpIgnoreCaseOption case_option = flags.is_ignore_case()
+    ? JSRegExpIgnoreCase
+    : JSRegExpDoNotIgnoreCase;
+  JSRegExpMultilineOption multiline_option = flags.is_multiline()
+    ? JSRegExpMultiline
+    : JSRegExpSingleLine;
 
   Handle<String> two_byte_pattern = StringToTwoByte(pattern);
 
@@ -328,8 +367,7 @@
     Handle<FixedArray> value = Factory::NewFixedArray(2);
     value->set(CAPTURE_INDEX, Smi::FromInt(number_of_captures));
     value->set(INTERNAL_INDEX, *internal);
-    re->set_type_tag(JSRegExp::JSCRE);
-    re->set_data(*value);
+    Factory::SetRegExpData(re, JSRegExp::JSCRE, pattern, flags, value);
 
     return re;
   }
@@ -499,16 +537,14 @@
 
 
 int RegExpImpl::JsreCapture(Handle<JSRegExp> re) {
-  Object* value = re->data();
-  ASSERT(value->IsFixedArray());
-  return Smi::cast(FixedArray::cast(value)->get(CAPTURE_INDEX))->value();
+  FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
+  return Smi::cast(value->get(CAPTURE_INDEX))->value();
 }
 
 
 ByteArray* RegExpImpl::JsreInternal(Handle<JSRegExp> re) {
-  Object* value = re->data();
-  ASSERT(value->IsFixedArray());
-  return ByteArray::cast(FixedArray::cast(value)->get(INTERNAL_INDEX));
+  FixedArray* value = FixedArray::cast(re->DataAt(JSRegExp::kJscreDataIndex));
+  return ByteArray::cast(value->get(INTERNAL_INDEX));
 }
 
 }}  // namespace v8::internal
diff --git a/src/jsregexp.h b/src/jsregexp.h
index 75d5c91..c05380d 100644
--- a/src/jsregexp.h
+++ b/src/jsregexp.h
@@ -62,7 +62,8 @@
                                    Handle<String> subject);
 
   static Handle<Object> AtomCompile(Handle<JSRegExp> re,
-                                    Handle<String> pattern);
+                                    Handle<String> pattern,
+                                    JSRegExp::Flags flags);
 
   static Handle<Object> AtomExec(Handle<JSRegExp> regexp,
                                  Handle<String> subject,
@@ -73,7 +74,7 @@
 
   static Handle<Object> JsreCompile(Handle<JSRegExp> re,
                                     Handle<String> pattern,
-                                    Handle<String> flags);
+                                    JSRegExp::Flags flags);
 
   static Handle<Object> JsreExec(Handle<JSRegExp> regexp,
                                  Handle<String> subject,
diff --git a/src/log.cc b/src/log.cc
index be76b96..796b98e 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -377,14 +377,12 @@
     return;
   }
 
-  if (regexp->type()->IsSmi()) {
-    switch (regexp->type_tag()) {
+  switch (regexp->TypeTag()) {
     case JSRegExp::ATOM:
       fprintf(logfile_, "a");
       break;
     default:
       break;
-    }
   }
   fprintf(logfile_, "/");
   LogString(Handle<String>::cast(source));
@@ -409,14 +407,14 @@
 #endif  // ENABLE_LOGGING_AND_PROFILING
 
 
-void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp) {
+void Logger::RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache) {
 #ifdef ENABLE_LOGGING_AND_PROFILING
   if (logfile_ == NULL || !FLAG_log_regexp) return;
   ScopedLock sl(mutex_);
 
   fprintf(logfile_, "regexp-compile,");
   LogRegExpSource(regexp);
-  fprintf(logfile_, "\n");
+  fprintf(logfile_, in_cache ? ",hit\n" : ",miss\n");
 #endif
 }
 
diff --git a/src/log.h b/src/log.h
index 69be103..c950b86 100644
--- a/src/log.h
+++ b/src/log.h
@@ -181,7 +181,7 @@
   // ==== Events logged by --log-regexp ====
   // Regexp compilation and execution events.
 
-  static void RegExpCompileEvent(Handle<JSRegExp> regexp);
+  static void RegExpCompileEvent(Handle<JSRegExp> regexp, bool in_cache);
 
   static void RegExpExecEvent(Handle<JSRegExp> regexp,
                               int start_index,
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index dc5cb60..d67544e 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -327,6 +327,7 @@
 
 static const char* TypeToString(InstanceType type) {
   switch (type) {
+    case INVALID_TYPE: return "INVALID";
     case MAP_TYPE: return "MAP";
     case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
     case SHORT_SYMBOL_TYPE:
@@ -659,19 +660,22 @@
 
 void JSRegExp::JSRegExpVerify() {
   JSObjectVerify();
-  ASSERT(type()->IsSmi() || type()->IsUndefined());
-  if (type()->IsSmi()) {
-    switch (type_tag()) {
-      case JSRegExp::JSCRE:
-        ASSERT(data()->IsFixedArray());
-        break;
-      default:
-        ASSERT_EQ(JSRegExp::ATOM, type_tag());
-        ASSERT(data()->IsString());
-        break;
+  ASSERT(data()->IsUndefined() || data()->IsFixedArray());
+  switch (TypeTag()) {
+    case JSRegExp::ATOM: {
+      FixedArray* arr = FixedArray::cast(data());
+      ASSERT(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
+      break;
     }
-  } else {
-    ASSERT(data()->IsUndefined());
+    case JSRegExp::JSCRE: {
+      FixedArray* arr = FixedArray::cast(data());
+      ASSERT(arr->get(JSRegExp::kJscreDataIndex)->IsFixedArray());
+      break;
+    }
+    default:
+      ASSERT_EQ(JSRegExp::NOT_COMPILED, TypeTag());
+      ASSERT(data()->IsUndefined());
+      break;
   }
 }
 
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 0cfa12b..beb6c0e 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -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;
@@ -510,7 +515,7 @@
 #define WRITE_BARRIER(object, offset) \
   Heap::RecordWrite(object->address(), offset);
 
-// CONITIONAL_WRITE_BARRIER must be issued after the actual
+// CONDITIONAL_WRITE_BARRIER must be issued after the actual
 // write due to the assert validating the written value.
 #define CONDITIONAL_WRITE_BARRIER(object, offset, mode) \
   if (mode == UPDATE_WRITE_BARRIER) { \
@@ -1130,10 +1135,7 @@
   // Fast case: do linear search for small arrays.
   const int kMaxElementsForLinearSearch = 8;
   if (name->IsSymbol() && nof < kMaxElementsForLinearSearch) {
-    for (int number = 0; number < nof; number++) {
-      if (name == GetKey(number)) return number;
-    }
-    return kNotFound;
+    return LinearSearch(name, nof);
   }
 
   // Slow case: perform binary search.
@@ -1274,36 +1276,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));
 }
 
 
@@ -1487,21 +1475,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);
 }
 
@@ -1509,21 +1490,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);
 }
@@ -1534,9 +1507,9 @@
 }
 
 
-void ConsString::set_first(Object* value) {
+void ConsString::set_first(Object* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kFirstOffset, value);
-  WRITE_BARRIER(this, kFirstOffset);
+  CONDITIONAL_WRITE_BARRIER(this, kFirstOffset, mode);
 }
 
 
@@ -1545,9 +1518,9 @@
 }
 
 
-void ConsString::set_second(Object* value) {
+void ConsString::set_second(Object* value, WriteBarrierMode mode) {
   WRITE_FIELD(this, kSecondOffset, value);
-  WRITE_BARRIER(this, kSecondOffset);
+  CONDITIONAL_WRITE_BARRIER(this, kSecondOffset, mode);
 }
 
 
@@ -2071,6 +2044,11 @@
 }
 
 
+int JSFunction::NumberOfLiterals() {
+  return literals()->length();
+}
+
+
 Object* JSBuiltinsObject::javascript_builtin(Builtins::JavaScript id) {
   ASSERT(0 <= id && id < kJSBuiltinsCount);
   return READ_FIELD(this, kJSBuiltinsOffset + (id * kPointerSize));
@@ -2161,16 +2139,19 @@
 
 
 ACCESSORS(JSRegExp, data, Object, kDataOffset)
-ACCESSORS(JSRegExp, type, Object, kTypeOffset)
 
 
-JSRegExp::Type JSRegExp::type_tag() {
-  return static_cast<JSRegExp::Type>(Smi::cast(type())->value());
+JSRegExp::Type JSRegExp::TypeTag() {
+  Object* data = this->data();
+  if (data->IsUndefined()) return JSRegExp::NOT_COMPILED;
+  Smi* smi = Smi::cast(FixedArray::cast(data)->get(kTagIndex));
+  return static_cast<JSRegExp::Type>(smi->value());
 }
 
 
-void JSRegExp::set_type_tag(JSRegExp::Type value) {
-  set_type(Smi::FromInt(value));
+Object* JSRegExp::DataAt(int index) {
+  ASSERT(TypeTag() != NOT_COMPILED);
+  return FixedArray::cast(data())->get(index);
 }
 
 
@@ -2351,7 +2332,7 @@
 
 
 void JSArray::SetContent(FixedArray* storage) {
-  set_length(Smi::FromInt(storage->length()));
+  set_length(Smi::FromInt(storage->length()), SKIP_WRITE_BARRIER);
   set_elements(storage);
 }
 
diff --git a/src/objects.cc b/src/objects.cc
index d12c3eb..e33d12e 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -2139,7 +2139,7 @@
     }
 
     // Check the context extension if any.
-    if (context->extension() != NULL) {
+    if (context->has_extension()) {
       return context->extension()->ReferencesObject(obj);
     }
   }
@@ -2580,14 +2580,15 @@
   if (obj->IsFailure()) return obj;
   // Fill in the content
   FixedArray* result = FixedArray::cast(obj);
+  WriteBarrierMode mode = result->GetWriteBarrierMode();
   for (int i = 0; i < len0; i++) {
-    result->set(i, get(i));
+    result->set(i, get(i), mode);
   }
   // Fill in the extra keys.
   int index = 0;
   for (int y = 0; y < len1; y++) {
     if (!HasKey(this, other->get(y))) {
-      result->set(len0 + index, other->get(y));
+      result->set(len0 + index, other->get(y), mode);
       index++;
     }
   }
@@ -2601,14 +2602,14 @@
   Object* obj = Heap::AllocateFixedArray(new_length);
   if (obj->IsFailure()) return obj;
   FixedArray* result = FixedArray::cast(obj);
-  WriteBarrierMode mode = result->GetWriteBarrierMode();
   // Copy the content
   int len = length();
   if (new_length < len) len = new_length;
+  result->set_map(map());
+  WriteBarrierMode mode = result->GetWriteBarrierMode();
   for (int i = 0; i < len; i++) {
     result->set(i, get(i), mode);
   }
-  result->set_map(map());
   return result;
 }
 
@@ -2876,6 +2877,14 @@
 }
 
 
+int DescriptorArray::LinearSearch(String* name, int len) {
+  for (int number = 0; number < len; number++) {
+    if (name->Equals(GetKey(number))) return number;
+  }
+  return kNotFound;
+}
+
+
 #ifdef DEBUG
 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   if (IsEmpty()) return other->IsEmpty();
@@ -3959,10 +3968,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);
   }
@@ -4047,11 +4058,6 @@
 }
 
 
-int JSFunction::NumberOfLiterals() {
-  return literals()->length();
-}
-
-
 Object* JSFunction::SetInstancePrototype(Object* value) {
   ASSERT(value->IsJSObject());
 
@@ -5555,6 +5561,46 @@
   String* string_;
 };
 
+// RegExpKey carries the source and flags of a regular expression as key.
+class RegExpKey : public HashTableKey {
+ public:
+  RegExpKey(String* string, JSRegExp::Flags flags)
+    : string_(string),
+      flags_(Smi::FromInt(flags.value())) { }
+
+  bool IsMatch(Object* obj) {
+    FixedArray* val = FixedArray::cast(obj);
+    return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
+        && (flags_ == val->get(JSRegExp::kFlagsIndex));
+  }
+
+  uint32_t Hash() { return RegExpHash(string_, flags_); }
+
+  HashFunction GetHashFunction() { return RegExpObjectHash; }
+
+  Object* GetObject() {
+    // Plain hash maps, which is where regexp keys are used, don't
+    // use this function.
+    UNREACHABLE();
+    return NULL;
+  }
+
+  static uint32_t RegExpObjectHash(Object* obj) {
+    FixedArray* val = FixedArray::cast(obj);
+    return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
+                      Smi::cast(val->get(JSRegExp::kFlagsIndex)));
+  }
+
+  static uint32_t RegExpHash(String* string, Smi* flags) {
+    return string->Hash() + flags->value();
+  }
+
+  bool IsStringKey() { return false; }
+
+  String* string_;
+  Smi* flags_;
+};
+
 // Utf8SymbolKey carries a vector of chars as key.
 class Utf8SymbolKey : public HashTableKey {
  public:
@@ -5829,6 +5875,15 @@
 }
 
 
+Object* CompilationCacheTable::LookupRegExp(String* src,
+                                            JSRegExp::Flags flags) {
+  RegExpKey key(src, flags);
+  int entry = FindEntry(&key);
+  if (entry == -1) return Heap::undefined_value();
+  return get(EntryToIndex(entry) + 1);
+}
+
+
 Object* CompilationCacheTable::Put(String* src, Object* value) {
   StringKey key(src);
   Object* obj = EnsureCapacity(1, &key);
@@ -5844,6 +5899,23 @@
 }
 
 
+Object* CompilationCacheTable::PutRegExp(String* src,
+                                         JSRegExp::Flags flags,
+                                         FixedArray* value) {
+  RegExpKey key(src, flags);
+  Object* obj = EnsureCapacity(1, &key);
+  if (obj->IsFailure()) return obj;
+
+  CompilationCacheTable* cache =
+      reinterpret_cast<CompilationCacheTable*>(obj);
+  int entry = cache->FindInsertionEntry(value, key.Hash());
+  cache->set(EntryToIndex(entry), value);
+  cache->set(EntryToIndex(entry) + 1, value);
+  cache->ElementAdded();
+  return cache;
+}
+
+
 // SymbolsKey used for HashTable where key is array of symbols.
 class SymbolsKey : public HashTableKey {
  public:
@@ -5974,7 +6046,7 @@
   int entry = cache->FindInsertionEntry(k, key.Hash());
   int index = EntryToIndex(entry);
   cache->set(index, k);
-  cache->set(index + 1, Smi::FromInt(value));
+  cache->set(index + 1, Smi::FromInt(value), SKIP_WRITE_BARRIER);
   cache->ElementAdded();
   return cache;
 }
diff --git a/src/objects.h b/src/objects.h
index e3bd522..d627935 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -395,29 +395,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,
@@ -535,6 +536,7 @@
   // Pseudo-types
   FIRST_NONSTRING_TYPE = MAP_TYPE,
   FIRST_TYPE = 0x0,
+  INVALID_TYPE = FIRST_TYPE - 1,
   LAST_TYPE = JS_FUNCTION_TYPE,
   // Boundaries for testing the type is a JavaScript "object".  Note that
   // function objects are not counted as objects, even though they are
@@ -624,6 +626,7 @@
   inline bool IsOddball();
   inline bool IsSharedFunctionInfo();
   inline bool IsJSValue();
+  inline bool IsStringWrapper();
   inline bool IsProxy();
   inline bool IsBoolean();
   inline bool IsJSArray();
@@ -1601,7 +1604,6 @@
   inline void Get(int descriptor_number, Descriptor* desc);
   inline void Set(int descriptor_number, Descriptor* desc);
 
-
   // Copy the descriptor array, insert a new descriptor and optionally
   // remove map transitions.  If the descriptor is already present, it is
   // replaced.  If a replaced descriptor is a real property (not a transition
@@ -1629,6 +1631,10 @@
   // with low=0 and high=2.
   int BinarySearch(String* name, int low, int high);
 
+  // Perform a linear search in the instance descriptors represented
+  // by this fixed array.  len is the number of descriptor indeces that are
+  // valid.  Does not require the descriptors to be sorted.
+  int LinearSearch(String* name, int len);
 
   // Allocates a DescriptorArray, but returns the singleton
   // empty descriptor array object if number_of_descriptors is 0.
@@ -1856,19 +1862,6 @@
 };
 
 
-class CompilationCacheTable: public HashTable<0, 2> {
- public:
-  // Find cached value for a string key, otherwise return null.
-  Object* Lookup(String* src);
-  Object* Put(String* src, Object* value);
-
-  static inline CompilationCacheTable* cast(Object* obj);
-
- private:
-  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
-};
-
-
 // MapCache.
 //
 // Maps keys that are a fixed array of symbols to a map.
@@ -2750,7 +2743,7 @@
 #endif
 
   // Returns the number of allocated literals.
-  int NumberOfLiterals();
+  inline int NumberOfLiterals();
 
   // Retrieve the global context from a function's literal array.
   static Context* GlobalContextFromLiterals(FixedArray* literals);
@@ -2907,18 +2900,28 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSValue);
 };
 
-
 // Regular expressions
 class JSRegExp: public JSObject {
  public:
-  enum Type { JSCRE, ATOM };
+  enum Type { NOT_COMPILED, JSCRE, ATOM };
+  enum Flag { NONE = 0, GLOBAL = 1, IGNORE_CASE = 2, MULTILINE = 4 };
 
-  inline Type type_tag();
-  inline void set_type_tag(Type value);
+  class Flags {
+   public:
+    explicit Flags(uint32_t value) : value_(value) { }
+    bool is_global() { return (value_ & GLOBAL) != 0; }
+    bool is_ignore_case() { return (value_ & IGNORE_CASE) != 0; }
+    bool is_multiline() { return (value_ & MULTILINE) != 0; }
+    uint32_t value() { return value_; }
+   private:
+    uint32_t value_;
+  };
 
-  DECL_ACCESSORS(type, Object)
   DECL_ACCESSORS(data, Object)
 
+  inline Type TypeTag();
+  inline Object* DataAt(int index);
+
   static inline JSRegExp* cast(Object* obj);
 
   // Dispatched behavior.
@@ -2927,9 +2930,32 @@
   void JSRegExpVerify();
 #endif
 
-  static const int kTypeOffset = JSObject::kHeaderSize;
-  static const int kDataOffset = kTypeOffset + kIntSize;
+  static const int kDataOffset = JSObject::kHeaderSize;
   static const int kSize = kDataOffset + kIntSize;
+
+  static const int kTagIndex = 0;
+  static const int kSourceIndex = kTagIndex + 1;
+  static const int kFlagsIndex = kSourceIndex + 1;
+  // These two are the same since the same entry is shared for
+  // different purposes in different types of regexps.
+  static const int kAtomPatternIndex = kFlagsIndex + 1;
+  static const int kJscreDataIndex = kFlagsIndex + 1;
+  static const int kDataSize = kAtomPatternIndex + 1;
+};
+
+
+class CompilationCacheTable: public HashTable<0, 2> {
+ public:
+  // Find cached value for a string key, otherwise return null.
+  Object* Lookup(String* src);
+  Object* LookupRegExp(String* source, JSRegExp::Flags flags);
+  Object* Put(String* src, Object* value);
+  Object* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
+
+  static inline CompilationCacheTable* cast(Object* obj);
+
+ private:
+  DISALLOW_IMPLICIT_CONSTRUCTORS(CompilationCacheTable);
 };
 
 
@@ -3130,8 +3156,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;
 
@@ -3152,14 +3178,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;
@@ -3347,11 +3373,13 @@
  public:
   // First object of the cons cell.
   inline Object* first();
-  inline void set_first(Object* first);
+  inline void set_first(Object* first,
+                        WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
 
   // Second object of the cons cell.
   inline Object* second();
-  inline void set_second(Object* second);
+  inline void set_second(Object* second,
+                         WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
 
   // Dispatched behavior.
   uint16_t ConsStringGet(int index);
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 4fdbf78..803df77 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -153,13 +153,6 @@
 }
 
 
-// Case-insensitive string comparisons. Use stricmp() on Win32. Usually defined
-// in strings.h.
-int strcasecmp(const char* s1, const char* s2) {
-  return _stricmp(s1, s2);
-}
-
-
 // Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually
 // defined in strings.h.
 int strncasecmp(const char* s1, const char* s2, int n) {
diff --git a/src/platform.h b/src/platform.h
index 0e33fa8..7238d70 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -68,7 +68,6 @@
 
 int random();
 
-int strcasecmp(const char* s1, const char* s2);
 int strncasecmp(const char* s1, const char* s2, int n);
 
 #else
diff --git a/src/runtime.cc b/src/runtime.cc
index 32246f3..dcd2b01 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -504,7 +504,7 @@
     // "declared" in the function context's extension context, or in the
     // global context.
     Handle<JSObject> context_ext;
-    if (context->extension() != NULL) {
+    if (context->has_extension()) {
       // The function context's extension context exists - use it.
       context_ext = Handle<JSObject>(context->extension());
     } else {
@@ -928,7 +928,7 @@
       literals->set(JSFunction::kLiteralGlobalContextIndex,
                     context->global_context());
     }
-    target->set_literals(*literals);
+    target->set_literals(*literals, SKIP_WRITE_BARRIER);
   }
 
   target->set_context(*context);
@@ -3134,11 +3134,16 @@
   const int length = frame->GetProvidedParametersCount();
   Object* result = Heap::AllocateArgumentsObject(callee, length);
   if (result->IsFailure()) return result;
-  FixedArray* array = FixedArray::cast(JSObject::cast(result)->elements());
-  ASSERT(array->length() == length);
-  WriteBarrierMode mode = array->GetWriteBarrierMode();
-  for (int i = 0; i < length; i++) {
-    array->set(i, frame->GetParameter(i), mode);
+  if (length > 0) {
+    Object* obj =  Heap::AllocateFixedArray(length);
+    if (obj->IsFailure()) return obj;
+    FixedArray* array = FixedArray::cast(obj);
+    ASSERT(array->length() == length);
+    WriteBarrierMode mode = array->GetWriteBarrierMode();
+    for (int i = 0; i < length; i++) {
+      array->set(i, frame->GetParameter(i), mode);
+    }
+    JSObject::cast(result)->set_elements(array);
   }
   return result;
 }
@@ -3154,11 +3159,22 @@
 
   Object* result = Heap::AllocateArgumentsObject(callee, length);
   if (result->IsFailure()) return result;
-  FixedArray* array = FixedArray::cast(JSObject::cast(result)->elements());
-  ASSERT(array->length() == length);
-  WriteBarrierMode mode = array->GetWriteBarrierMode();
-  for (int i = 0; i < length; i++) {
-    array->set(i, *--parameters, mode);
+  ASSERT(Heap::InNewSpace(result));
+
+  // Allocate the elements if needed.
+  if (length > 0) {
+    // Allocate the fixed array.
+    Object* obj = Heap::AllocateRawFixedArray(length);
+    if (obj->IsFailure()) return obj;
+    reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
+    FixedArray* array = FixedArray::cast(obj);
+    array->set_length(length);
+    WriteBarrierMode mode = array->GetWriteBarrierMode();
+    for (int i = 0; i < length; i++) {
+      array->set(i, *--parameters, mode);
+    }
+    JSObject::cast(result)->set_elements(FixedArray::cast(obj),
+                                         SKIP_WRITE_BARRIER);
   }
   return result;
 }
@@ -3331,7 +3347,7 @@
   Handle<Object> holder =
       context->Lookup(name, flags, &index, &attributes);
 
-  if (index < 0 && *holder != NULL) {
+  if (index < 0 && !holder.is_null()) {
     ASSERT(holder->IsJSObject());
     return *holder;
   }
@@ -3348,61 +3364,48 @@
 // compiler to do the right thing.
 //
 // TODO(1236026): This is a non-portable hack that should be removed.
-typedef uint64_t ObjPair;
-ObjPair MakePair(Object* x, Object* y) {
+typedef uint64_t ObjectPair;
+static inline ObjectPair MakePair(Object* x, Object* y) {
   return reinterpret_cast<uint32_t>(x) |
-         (reinterpret_cast<ObjPair>(y) << 32);
+      (reinterpret_cast<ObjectPair>(y) << 32);
 }
 
 
-static Object* Unhole(Object* x, PropertyAttributes attributes) {
+static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
   ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
   USE(attributes);
   return x->IsTheHole() ? Heap::undefined_value() : x;
 }
 
 
-static Object* ComputeContextSlotReceiver(Object* holder) {
-  // If the "property" we were looking for is a local variable or an
-  // argument in a context, the receiver is the global object; see
-  // ECMA-262, 3rd., 10.1.6 and 10.2.3.
-  HeapObject* object = HeapObject::cast(holder);
+static JSObject* ComputeReceiverForNonGlobal(JSObject* holder) {
+  ASSERT(!holder->IsGlobalObject());
   Context* top = Top::context();
-  if (holder->IsContext()) return top->global()->global_receiver();
-
-  // TODO(125): Find a better - and faster way - of checking for
-  // arguments and context extension objects. This kinda sucks.
+  // Get the context extension function.
   JSFunction* context_extension_function =
       top->global_context()->context_extension_function();
-  JSObject* arguments_boilerplate =
-      top->global_context()->arguments_boilerplate();
-  JSFunction* arguments_function =
-      JSFunction::cast(arguments_boilerplate->map()->constructor());
-  // If the holder is an arguments object or a context extension then the
-  // receiver is also the global object;
-  Object* constructor = HeapObject::cast(holder)->map()->constructor();
-  if (constructor == context_extension_function ||
-      constructor == arguments_function) {
-    return Top::context()->global()->global_receiver();
-  }
-
-  // If the holder is a global object, we have to be careful to wrap
-  // it in its proxy if necessary.
-  if (object->IsGlobalObject()) {
-    return GlobalObject::cast(object)->global_receiver();
-  } else {
-    return object;
-  }
+  // If the holder isn't a context extension object, we just return it
+  // as the receiver. This allows arguments objects to be used as
+  // receivers, but only if they are put in the context scope chain
+  // explicitly via a with-statement.
+  Object* constructor = holder->map()->constructor();
+  if (constructor != context_extension_function) return holder;
+  // Fall back to using the global object as the receiver if the
+  // property turns out to be a local variable allocated in a context
+  // extension object - introduced via eval.
+  return top->global()->global_receiver();
 }
 
 
-static ObjPair LoadContextSlotHelper(Arguments args, bool throw_error) {
+static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) {
   HandleScope scope;
   ASSERT(args.length() == 2);
 
-  if (!args[0]->IsContext()) return MakePair(IllegalOperation(), NULL);
+  if (!args[0]->IsContext() || !args[1]->IsString()) {
+    return MakePair(IllegalOperation(), NULL);
+  }
   Handle<Context> context = args.at<Context>(0);
-  Handle<String> name(String::cast(args[1]));
+  Handle<String> name = args.at<String>(1);
 
   int index;
   PropertyAttributes attributes;
@@ -3410,29 +3413,31 @@
   Handle<Object> holder =
       context->Lookup(name, flags, &index, &attributes);
 
+  // If the index is non-negative, the slot has been found in a local
+  // variable or a parameter. Read it from the context object or the
+  // arguments object.
   if (index >= 0) {
-    Handle<Object> receiver =
-        Handle<Object>(ComputeContextSlotReceiver(*holder));
-    Handle<Object> value;
-    if (holder->IsContext()) {
-      value = Handle<Object>(Context::cast(*holder)->get(index));
-    } else {
-      // Arguments object.
-      value = Handle<Object>(JSObject::cast(*holder)->GetElement(index));
-    }
-    return MakePair(Unhole(*value, attributes), *receiver);
+    // If the "property" we were looking for is a local variable or an
+    // argument in a context, the receiver is the global object; see
+    // ECMA-262, 3rd., 10.1.6 and 10.2.3.
+    JSObject* receiver = Top::context()->global()->global_receiver();
+    Object* value = (holder->IsContext())
+        ? Context::cast(*holder)->get(index)
+        : JSObject::cast(*holder)->GetElement(index);
+    return MakePair(Unhole(value, attributes), receiver);
   }
 
-  if (*holder != NULL) {
-    ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
-    // Note: As of 5/29/2008, GetProperty does the "unholing" and so
-    // this call here is redundant. We left it anyway, to be explicit;
-    // also it's not clear why GetProperty should do the unholing in
-    // the first place.
-    return MakePair(
-        Unhole(Handle<JSObject>::cast(holder)->GetProperty(*name),
-               attributes),
-        ComputeContextSlotReceiver(*holder));
+  // If the holder is found, we read the property from it.
+  if (!holder.is_null() && holder->IsJSObject()) {
+    JSObject* object = JSObject::cast(*holder);
+    ASSERT(object->HasProperty(*name));
+    JSObject* receiver = (object->IsGlobalObject())
+        ? GlobalObject::cast(object)->global_receiver()
+        : ComputeReceiverForNonGlobal(object);
+    // No need to unhole the value here. This is taken care of by the
+    // GetProperty function.
+    Object* value = object->GetProperty(*name);
+    return MakePair(value, receiver);
   }
 
   if (throw_error) {
@@ -3447,12 +3452,12 @@
 }
 
 
-static ObjPair Runtime_LoadContextSlot(Arguments args) {
+static ObjectPair Runtime_LoadContextSlot(Arguments args) {
   return LoadContextSlotHelper(args, true);
 }
 
 
-static ObjPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
+static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
   return LoadContextSlotHelper(args, false);
 }
 
@@ -3491,7 +3496,7 @@
   // It is either in an JSObject extension context or it was not found.
   Handle<JSObject> context_ext;
 
-  if (*holder != NULL) {
+  if (!holder.is_null()) {
     // The property exists in the extension context.
     context_ext = Handle<JSObject>::cast(holder);
   } else {
@@ -3564,10 +3569,10 @@
 }
 
 
-static Object* Runtime_DebugBreak(Arguments args) {
+static Object* DebugBreakHelper() {
   // Just continue if breaks are disabled.
   if (Debug::disable_break()) {
-    return args[0];
+    return Heap::undefined_value();
   }
 
   // Don't break in system functions. If the current function is
@@ -3579,7 +3584,7 @@
   if (fun->IsJSFunction()) {
     GlobalObject* global = JSFunction::cast(fun)->context()->global();
     if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
-      return args[0];
+      return Heap::undefined_value();
     }
   }
 
@@ -3590,14 +3595,20 @@
   // Enter the debugger. Just continue if we fail to enter the debugger.
   EnterDebugger debugger;
   if (debugger.FailedToEnter()) {
-    return args[0];
+    return Heap::undefined_value();
   }
 
   // Notify the debug event listeners.
   Debugger::OnDebugBreak(Factory::undefined_value());
 
   // Return to continue execution.
-  return args[0];
+  return Heap::undefined_value();
+}
+
+
+static Object* Runtime_DebugBreak(Arguments args) {
+  ASSERT(args.length() == 0);
+  return DebugBreakHelper();
 }
 
 
@@ -3609,7 +3620,7 @@
 
   // If not real stack overflow the stack guard was used to interrupt
   // execution for another purpose.
-  if (StackGuard::IsDebugBreak()) Runtime_DebugBreak(args);
+  if (StackGuard::IsDebugBreak()) DebugBreakHelper();
   if (StackGuard::IsPreempted()) RuntimePreempt(args);
   if (StackGuard::IsInterrupted()) {
     // interrupt
@@ -3707,9 +3718,10 @@
 
 
 static Object* Runtime_TraceEnter(Arguments args) {
+  ASSERT(args.length() == 0);
   NoHandleAllocation ha;
   PrintTransition(NULL);
-  return args[0];  // return TOS
+  return Heap::undefined_value();
 }
 
 
@@ -3748,10 +3760,10 @@
 
 
 static Object* Runtime_DebugTrace(Arguments args) {
-  ASSERT(args.length() == 1);
+  ASSERT(args.length() == 0);
   NoHandleAllocation ha;
   Top::PrintStack();
-  return args[0];  // return TOS
+  return Heap::undefined_value();
 }
 
 
@@ -4484,7 +4496,7 @@
       Handle<String> name = info.LocalName(i);
       // Traverse the context chain to the function context as all local
       // variables stored in the context will be on the function context.
-      while (context->previous() != NULL) {
+      while (!context->is_function_context()) {
         context = Handle<Context>(context->previous());
       }
       ASSERT(context->is_function_context());
@@ -4900,13 +4912,13 @@
   }
 
   const int length = frame->GetProvidedParametersCount();
-  Handle<Object> arguments = Factory::NewArgumentsObject(function, length);
-  FixedArray* array = FixedArray::cast(JSObject::cast(*arguments)->elements());
-  ASSERT(array->length() == length);
+  Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
+  Handle<FixedArray> array = Factory::NewFixedArray(length);
   WriteBarrierMode mode = array->GetWriteBarrierMode();
   for (int i = 0; i < length; i++) {
     array->set(i, frame->GetParameter(i), mode);
   }
+  arguments->set_elements(*array);
   return arguments;
 }
 
@@ -5000,7 +5012,7 @@
   }
   // Finally copy any properties from the function context extension. This will
   // be variables introduced by eval.
-  if (function_context->extension() != NULL &&
+  if (function_context->has_extension() &&
       !function_context->IsGlobalContext()) {
     Handle<JSObject> ext(JSObject::cast(function_context->extension()));
     Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
diff --git a/src/runtime.h b/src/runtime.h
index 63bdc87..463698c 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -277,10 +277,10 @@
   \
   /* Debugging */ \
   F(DebugPrint, 1) \
-  F(DebugTrace, 1) \
-  F(TraceEnter, 1) \
+  F(DebugTrace, 0) \
+  F(TraceEnter, 0) \
   F(TraceExit, 1) \
-  F(DebugBreak, 1) \
+  F(DebugBreak, 0) \
   F(FunctionGetAssemblerCode, 1) \
   F(Abort, 2) \
   \
diff --git a/src/runtime.js b/src/runtime.js
index 1355356..5e73d41 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -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);
     }
   }
diff --git a/src/stub-cache-arm.cc b/src/stub-cache-arm.cc
index 085c04a..2ef657e 100644
--- a/src/stub-cache-arm.cc
+++ b/src/stub-cache-arm.cc
@@ -220,15 +220,15 @@
 
   const int argc = arguments().immediate();
 
-  // Get the receiver of the function from the stack into r1.
-  __ ldr(r1, MemOperand(sp, argc * kPointerSize));
+  // Get the receiver of the function from the stack into r0.
+  __ ldr(r0, MemOperand(sp, argc * kPointerSize));
   // Check that the receiver isn't a smi.
-  __ tst(r1, Operand(kSmiTagMask));
+  __ tst(r0, Operand(kSmiTagMask));
   __ b(eq, &miss);
 
   // Do the right check and compute the holder register.
   Register reg =
-      __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
+      __ CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
   GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
 
   // Check that the function really is a function.
@@ -240,8 +240,12 @@
   __ cmp(r2, Operand(JS_FUNCTION_TYPE));
   __ b(ne, &miss);
 
-  // Patch the function on the stack; 1 ~ receiver.
-  __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
+    __ str(r3, MemOperand(sp, argc * kPointerSize));
+  }
 
   // Invoke the function.
   __ InvokeFunction(r1, arguments(), JUMP_FUNCTION);
@@ -277,10 +281,21 @@
     __ b(eq, &miss);
   }
 
+  // Make sure that it's okay not to patch the on stack receiver
+  // unless we're doing a receiver map check.
+  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
+
   switch (check) {
     case RECEIVER_MAP_CHECK:
       // Check that the maps haven't changed.
       __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
+
+      // Patch the receiver on the stack with the global proxy if
+      // necessary.
+      if (object->IsGlobalObject()) {
+        __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
+        __ str(r3, MemOperand(sp, argc * kPointerSize));
+      }
       break;
 
     case STRING_CHECK:
@@ -352,9 +367,6 @@
   __ mov(r1, Operand(Handle<JSFunction>(function)));
   __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
 
-  // Patch the function on the stack; 1 ~ receiver.
-  __ str(r1, MemOperand(sp, (argc + 1) * kPointerSize));
-
   // Jump to the cached code (tail call).
   Handle<Code> code(function->code());
   ParameterCount expected(function->shared()->formal_parameter_count());
@@ -800,19 +812,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();
 }
diff --git a/src/stub-cache-ia32.cc b/src/stub-cache-ia32.cc
index 37f855a..f59ed57 100644
--- a/src/stub-cache-ia32.cc
+++ b/src/stub-cache-ia32.cc
@@ -159,71 +159,55 @@
 }
 
 
-void StubCompiler::GenerateLoadShortStringLength(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 | 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.
-  __ 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 | 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);
 }
 
 
@@ -478,6 +462,7 @@
   __ CallRuntime(Runtime::kLazyCompile, 1);
   __ pop(edi);
 
+  // Tear down temporary frame.
   __ LeaveInternalFrame();
 
   // Do a tail-call of the compiled function.
@@ -519,6 +504,13 @@
   __ cmp(ebx, JS_FUNCTION_TYPE);
   __ j(not_equal, &miss, not_taken);
 
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
   // Invoke the function.
   __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
 
@@ -552,10 +544,21 @@
     __ j(zero, &miss, not_taken);
   }
 
+  // Make sure that it's okay not to patch the on stack receiver
+  // unless we're doing a receiver map check.
+  ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
+
   switch (check) {
     case RECEIVER_MAP_CHECK:
       // Check that the maps haven't changed.
       __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+
+      // Patch the receiver on the stack with the global proxy if
+      // necessary.
+      if (object->IsGlobalObject()) {
+        __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+        __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+      }
       break;
 
     case STRING_CHECK:
@@ -657,6 +660,7 @@
 
   // Get the receiver from the stack.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
+
   // Check that the receiver isn't a smi.
   __ test(edx, Immediate(kSmiTagMask));
   __ j(zero, &miss, not_taken);
@@ -697,6 +701,13 @@
   __ cmp(ebx, JS_FUNCTION_TYPE);
   __ j(not_equal, &miss, not_taken);
 
+  // Patch the receiver on the stack with the global proxy if
+  // necessary.
+  if (object->IsGlobalObject()) {
+    __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
+    __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
+  }
+
   // Invoke the function.
   __ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
 
@@ -1140,7 +1151,7 @@
 }
 
 
-Object* KeyedLoadStubCompiler::CompileLoadShortStringLength(String* name) {
+Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
   // ----------- S t a t e -------------
   //  -- esp[0] : return address
   //  -- esp[4] : name
@@ -1157,61 +1168,7 @@
   __ 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) {
-  // ----------- 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);
-
-  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);
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 8d7c395..2904889 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -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));
diff --git a/src/stub-cache.h b/src/stub-cache.h
index 4fb78da..5d67afe 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -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:
diff --git a/src/top.cc b/src/top.cc
index a78ba32..29b7861 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -806,7 +806,7 @@
   if (report_exception) {
     if (message != NULL) {
       MessageHandler::ReportMessage(message);
-    } else {
+    } else if (!message_obj.is_null()) {
       MessageHandler::ReportMessage(location, message_obj);
     }
   }
diff --git a/src/top.h b/src/top.h
index f7595b1..866487c 100644
--- a/src/top.h
+++ b/src/top.h
@@ -300,14 +300,14 @@
 };
 
 
-// TODO(122): If the GCC version is 4.2.0 or higher an additional field is added
-// to this class as a workarround for a bug in the generated code found with
-// GCC 4.2.3.
+// If the GCC version is 4.1.x or 4.2.x an additional field is added to the
+// class as a workarround for a bug in the generated code found with these
+// versions of GCC. See V8 issue 122 for details.
 class SaveContext BASE_EMBEDDED {
  public:
   SaveContext() :
       context_(Top::context()),
-#if __GNUC_VERSION__ >= 40200
+#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
       dummy_(Top::context()),
 #endif
       prev_(Top::save_context()) {
@@ -324,7 +324,7 @@
 
  private:
   Handle<Context> context_;
-#if __GNUC_VERSION__ >= 40200
+#if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
   Handle<Context> dummy_;
 #endif
   SaveContext* prev_;
diff --git a/src/v8-counters.h b/src/v8-counters.h
index 9819cdc..6eb7426 100644
--- a/src/v8-counters.h
+++ b/src/v8-counters.h
@@ -73,6 +73,8 @@
   SC(arguments_adaptors, V8.ArgumentsAdaptors)                   \
   SC(compilation_cache_hits, V8.CompilationCacheHits)            \
   SC(compilation_cache_misses, V8.CompilationCacheMisses)        \
+  SC(regexp_cache_hits, V8.RegExpCacheHits)                      \
+  SC(regexp_cache_misses, V8.RegExpCacheMisses)                  \
   /* Amount of evaled source code. */                            \
   SC(total_eval_size, V8.TotalEvalSize)                          \
   /* Amount of loaded source code. */                            \