Version 3.9.0

Reduce memory use immediately after starting V8.

Stability fixes and performance improvements on all platforms.

git-svn-id: http://v8.googlecode.com/svn/trunk@10576 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/runtime.cc b/src/runtime.cc
index f95ecdf..7f3d318 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -428,6 +428,23 @@
 }
 
 
+MaybeObject* TransitionElements(Handle<Object> object,
+                                ElementsKind to_kind,
+                                Isolate* isolate) {
+  HandleScope scope(isolate);
+  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
+  ElementsKind from_kind =
+      Handle<JSObject>::cast(object)->map()->elements_kind();
+  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
+    Handle<Object> result = JSObject::TransitionElementsKind(
+        Handle<JSObject>::cast(object), to_kind);
+    if (result.is_null()) return isolate->ThrowIllegalOperation();
+    return *result;
+  }
+  return isolate->ThrowIllegalOperation();
+}
+
+
 static const int kSmiOnlyLiteralMinimumLength = 1024;
 
 
@@ -446,25 +463,13 @@
   Handle<FixedArrayBase> constant_elements_values(
       FixedArrayBase::cast(elements->get(1)));
 
-  ASSERT(FLAG_smi_only_arrays || constant_elements_kind == FAST_ELEMENTS ||
-         constant_elements_kind == FAST_SMI_ONLY_ELEMENTS);
-  bool allow_literal_kind_transition = FLAG_smi_only_arrays &&
-      constant_elements_kind > object->GetElementsKind();
-
-  if (!FLAG_smi_only_arrays &&
-      constant_elements_values->length() > kSmiOnlyLiteralMinimumLength &&
-      constant_elements_kind != object->GetElementsKind()) {
-    allow_literal_kind_transition = true;
-  }
-
-  // If the ElementsKind of the constant values of the array literal are less
-  // specific than the ElementsKind of the boilerplate array object, change the
-  // boilerplate array object's map to reflect that kind.
-  if (allow_literal_kind_transition) {
-    Handle<Map> transitioned_array_map =
-        isolate->factory()->GetElementsTransitionMap(object,
-                                                     constant_elements_kind);
-    object->set_map(*transitioned_array_map);
+  Context* global_context = isolate->context()->global_context();
+  if (constant_elements_kind == FAST_SMI_ONLY_ELEMENTS) {
+    object->set_map(Map::cast(global_context->smi_js_array_map()));
+  } else if (constant_elements_kind == FAST_DOUBLE_ELEMENTS) {
+    object->set_map(Map::cast(global_context->double_js_array_map()));
+  } else {
+    object->set_map(Map::cast(global_context->object_js_array_map()));
   }
 
   Handle<FixedArrayBase> copied_elements_values;
@@ -509,6 +514,16 @@
   }
   object->set_elements(*copied_elements_values);
   object->set_length(Smi::FromInt(copied_elements_values->length()));
+
+  //  Ensure that the boilerplate object has FAST_ELEMENTS, unless the flag is
+  //  on or the object is larger than the threshold.
+  if (!FLAG_smi_only_arrays &&
+      constant_elements_values->length() < kSmiOnlyLiteralMinimumLength) {
+    if (object->GetElementsKind() != FAST_ELEMENTS) {
+      CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
+    }
+  }
+
   return object;
 }
 
@@ -4202,23 +4217,6 @@
 }
 
 
-MaybeObject* TransitionElements(Handle<Object> object,
-                                ElementsKind to_kind,
-                                Isolate* isolate) {
-  HandleScope scope(isolate);
-  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
-  ElementsKind from_kind =
-      Handle<JSObject>::cast(object)->map()->elements_kind();
-  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
-    Handle<Object> result = JSObject::TransitionElementsKind(
-        Handle<JSObject>::cast(object), to_kind);
-    if (result.is_null()) return isolate->ThrowIllegalOperation();
-    return *result;
-  }
-  return isolate->ThrowIllegalOperation();
-}
-
-
 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
   NoHandleAllocation ha;
@@ -10236,7 +10234,7 @@
   } else {
     elements_kind = DICTIONARY_ELEMENTS;
   }
-  maybe_new_map = to->GetElementsTransitionMap(elements_kind);
+  maybe_new_map = to->GetElementsTransitionMap(isolate, elements_kind);
   Object* new_map;
   if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   to->set_map(Map::cast(new_map));
@@ -10749,6 +10747,11 @@
         ? deoptimized_frame_->GetExpression(index)
         : frame_->GetExpression(index);
   }
+  int GetSourcePosition() {
+    return is_optimized_
+        ? deoptimized_frame_->GetSourcePosition()
+        : frame_->LookupCode()->SourcePosition(frame_->pc());
+  }
 
   // To inspect all the provided arguments the frame might need to be
   // replaced with the arguments frame.
@@ -10854,9 +10857,8 @@
   // Get the frame id.
   Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
 
-  // Find source position.
-  int position =
-      it.frame()->LookupCode()->SourcePosition(it.frame()->pc());
+  // Find source position in unoptimized code.
+  int position = frame_inspector.GetSourcePosition();
 
   // Check for constructor frame. Inlined frames cannot be construct calls.
   bool inlined_frame = is_optimized && inlined_jsframe_index != 0;