Upgrade V8 to 3.0.4
authorRyan Dahl <ry@tinyclouds.org>
Tue, 21 Dec 2010 18:24:08 +0000 (10:24 -0800)
committerRyan Dahl <ry@tinyclouds.org>
Tue, 21 Dec 2010 18:24:08 +0000 (10:24 -0800)
67 files changed:
deps/v8/ChangeLog
deps/v8/SConstruct
deps/v8/include/v8.h
deps/v8/src/SConscript
deps/v8/src/api.cc
deps/v8/src/arm/code-stubs-arm.cc
deps/v8/src/arm/lithium-arm.cc
deps/v8/src/arm/lithium-codegen-arm.cc
deps/v8/src/arm/macro-assembler-arm.cc
deps/v8/src/arm/macro-assembler-arm.h
deps/v8/src/array.js
deps/v8/src/assembler.cc
deps/v8/src/assembler.h
deps/v8/src/builtins.cc
deps/v8/src/code-stubs.h
deps/v8/src/codegen.cc
deps/v8/src/counters.h
deps/v8/src/date.js
deps/v8/src/debug.cc
deps/v8/src/deoptimizer.cc
deps/v8/src/deoptimizer.h
deps/v8/src/flag-definitions.h
deps/v8/src/full-codegen.cc
deps/v8/src/heap-profiler.cc
deps/v8/src/heap.cc
deps/v8/src/heap.h
deps/v8/src/hydrogen-instructions.cc
deps/v8/src/hydrogen-instructions.h
deps/v8/src/hydrogen.cc
deps/v8/src/hydrogen.h
deps/v8/src/ia32/code-stubs-ia32.cc
deps/v8/src/ia32/code-stubs-ia32.h
deps/v8/src/ia32/codegen-ia32.cc
deps/v8/src/ia32/full-codegen-ia32.cc
deps/v8/src/ia32/lithium-codegen-ia32.cc
deps/v8/src/ia32/lithium-codegen-ia32.h
deps/v8/src/ia32/lithium-ia32.cc
deps/v8/src/objects-debug.cc
deps/v8/src/objects.cc
deps/v8/src/objects.h
deps/v8/src/parser.cc
deps/v8/src/platform-nullos.cc
deps/v8/src/platform-posix.cc
deps/v8/src/platform-win32.cc
deps/v8/src/platform.h
deps/v8/src/profile-generator.cc
deps/v8/src/property.cc
deps/v8/src/property.h
deps/v8/src/regexp.js
deps/v8/src/runtime.cc
deps/v8/src/spaces.cc
deps/v8/src/spaces.h
deps/v8/src/string-stream.cc
deps/v8/src/string-stream.h
deps/v8/src/string.js
deps/v8/src/utils.cc
deps/v8/src/v8-counters.h
deps/v8/src/v8utils.h
deps/v8/src/version.cc
deps/v8/src/x64/codegen-x64.cc
deps/v8/test/cctest/test-heap.cc
deps/v8/test/mjsunit/array-slice.js
deps/v8/test/mjsunit/array-sort.js
deps/v8/test/mjsunit/with-readonly.js [new file with mode: 0644]
deps/v8/tools/gyp/v8.gyp
deps/v8/tools/v8.xcodeproj/project.pbxproj
deps/v8/tools/visual_studio/debug.vsprops

index f1b47b0..c81d7a7 100644 (file)
@@ -1,3 +1,14 @@
+2010-12-21: Version 3.0.4
+
+        Added Date::ResetCache() to the API so that the cached values in the
+        Date object can be reset to allow live DST / timezone changes.
+
+        Extended existing support for printing (while debugging) the contents
+        of objects.  Added support for printing objects from release builds.
+
+        Fixed V8 issues 989, 1006, and 1007.
+
+
 2010-12-17: Version 3.0.3
 
         Reapplied all changes for version 3.0.1.
index 41c9fae..5908be1 100644 (file)
@@ -108,11 +108,14 @@ LIBRARY_FLAGS = {
       'CPPDEFINES': ['V8_INTERPRETED_REGEXP']
     },
     'mode:debug': {
-      'CPPDEFINES': ['V8_ENABLE_CHECKS']
+      'CPPDEFINES': ['V8_ENABLE_CHECKS', 'OBJECT_PRINT']
     },
     'vmstate:on': {
       'CPPDEFINES':   ['ENABLE_VMSTATE_TRACKING'],
     },
+    'objectprint:on': {
+      'CPPDEFINES':   ['OBJECT_PRINT'],
+    },
     'protectheap:on': {
       'CPPDEFINES':   ['ENABLE_VMSTATE_TRACKING', 'ENABLE_HEAP_PROTECTION'],
     },
@@ -225,8 +228,7 @@ LIBRARY_FLAGS = {
       'LINKFLAGS':    ['-m64'],
     },
     'prof:oprofile': {
-      'CPPDEFINES':   ['ENABLE_OPROFILE_AGENT'],
-      'LIBS': ['opagent', 'bfd']
+      'CPPDEFINES':   ['ENABLE_OPROFILE_AGENT']
     }
   },
   'msvc': {
@@ -711,6 +713,11 @@ SIMPLE_OPTIONS = {
     'default': 'off',
     'help': 'enable VM state tracking'
   },
+  'objectprint': {
+    'values': ['on', 'off'],
+    'default': 'off',
+    'help': 'enable object printing'
+  },
   'protectheap': {
     'values': ['on', 'off'],
     'default': 'off',
index 82de6b8..2c0f350 100644 (file)
@@ -1355,6 +1355,21 @@ class Date : public Value {
   V8EXPORT double NumberValue() const;
 
   static inline Date* Cast(v8::Value* obj);
+
+  /**
+   * Notification that the embedder has changed the time zone,
+   * daylight savings time, or other date / time configuration
+   * parameters.  V8 keeps a cache of various values used for
+   * date / time computation.  This notification will reset
+   * those cached values for the current context so that date /
+   * time configuration changes would be reflected in the Date
+   * object.
+   *
+   * This API should not be called more than needed as it will
+   * negatively impact the performance of date operations.
+   */
+  V8EXPORT static void DateTimeConfigurationChangeNotification();
+
  private:
   V8EXPORT static void CheckCast(v8::Value* obj);
 };
index 5d79072..8ccc6f2 100755 (executable)
@@ -231,7 +231,8 @@ SOURCES = {
   'mode:release': [],
   'mode:debug': [
     'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
-  ]
+  ],
+  'objectprint:on': ['objects-debug.cc']
 }
 
 
index b85d658..110468e 100644 (file)
@@ -3802,6 +3802,35 @@ double v8::Date::NumberValue() const {
 }
 
 
+void v8::Date::DateTimeConfigurationChangeNotification() {
+  ON_BAILOUT("v8::Date::DateTimeConfigurationChangeNotification()", return);
+  LOG_API("Date::DateTimeConfigurationChangeNotification");
+  ENTER_V8;
+
+  HandleScope scope;
+
+  // Get the function ResetDateCache (defined in date-delay.js).
+  i::Handle<i::String> func_name_str =
+      i::Factory::LookupAsciiSymbol("ResetDateCache");
+  i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
+  i::Object* object_func;
+  if (!result->ToObject(&object_func)) {
+    return;
+  }
+
+  if (object_func->IsJSFunction()) {
+    i::Handle<i::JSFunction> func =
+        i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
+
+    // Call ResetDateCache(0 but expect no exceptions:
+    bool caught_exception = false;
+    i::Handle<i::Object> result =
+        i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
+        &caught_exception);
+  }
+}
+
+
 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
   char flags_buf[3];
   int num_flags = 0;
index 3670765..5ec8584 100644 (file)
@@ -2893,80 +2893,97 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
 }
 
 
-// This stub performs an instanceof, calling the builtin function if
-// necessary.  Uses r1 for the object, r0 for the function that it may
-// be an instance of (these are fetched from the stack).
+// Uses registers r0 to r4. Expected input is
+// function in r0 (or at sp+1*ptrsz) and object in
+// r1 (or at sp), depending on whether or not
+// args_in_registers() is true.
 void InstanceofStub::Generate(MacroAssembler* masm) {
-  // Get the object - slow case for smis (we may need to throw an exception
-  // depending on the rhs).
-  Label slow, loop, is_instance, is_not_instance;
-  __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
-  __ BranchOnSmi(r0, &slow);
+  // Fixed register usage throughout the stub:
+  const Register object = r1;  // Object (lhs).
+  const Register map = r3;  // Map of the object.
+  const Register function = r0;  // Function (rhs).
+  const Register prototype = r4;  // Prototype of the function.
+  const Register scratch = r2;
+  Label slow, loop, is_instance, is_not_instance, not_js_object;
+  if (!args_in_registers()) {
+    __ ldr(function, MemOperand(sp, 1 * kPointerSize));
+    __ ldr(object, MemOperand(sp, 0));
+  }
 
-  // Check that the left hand is a JS object and put map in r3.
-  __ CompareObjectType(r0, r3, r2, FIRST_JS_OBJECT_TYPE);
-  __ b(lt, &slow);
-  __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
-  __ b(gt, &slow);
-
-  // Get the prototype of the function (r4 is result, r2 is scratch).
-  __ ldr(r1, MemOperand(sp, 0));
-  // r1 is function, r3 is map.
+  // Check that the left hand is a JS object and load map.
+  __ BranchOnSmi(object, &slow);
+  __ IsObjectJSObjectType(object, map, scratch, &slow);
 
   // Look up the function and the map in the instanceof cache.
   Label miss;
   __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
-  __ cmp(r1, ip);
+  __ cmp(object, ip);
   __ b(ne, &miss);
   __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
-  __ cmp(r3, ip);
+  __ cmp(map, ip);
   __ b(ne, &miss);
-  __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
-  __ pop();
-  __ pop();
-  __ mov(pc, Operand(lr));
+  __ LoadRoot(function, Heap::kInstanceofCacheAnswerRootIndex);
+  __ Ret(args_in_registers() ? 0 : 2);
 
   __ bind(&miss);
-  __ TryGetFunctionPrototype(r1, r4, r2, &slow);
+  __ TryGetFunctionPrototype(object, prototype, scratch, &slow);
 
   // Check that the function prototype is a JS object.
-  __ BranchOnSmi(r4, &slow);
-  __ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE);
-  __ b(lt, &slow);
-  __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE));
-  __ b(gt, &slow);
+  __ BranchOnSmi(prototype, &slow);
+  __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
 
-  __ StoreRoot(r1, Heap::kInstanceofCacheFunctionRootIndex);
-  __ StoreRoot(r3, Heap::kInstanceofCacheMapRootIndex);
+  __ StoreRoot(object, Heap::kInstanceofCacheFunctionRootIndex);
+  __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
 
   // Register mapping: r3 is object map and r4 is function prototype.
   // Get prototype of object into r2.
-  __ ldr(r2, FieldMemOperand(r3, Map::kPrototypeOffset));
+  __ ldr(scratch, FieldMemOperand(map, Map::kPrototypeOffset));
 
   // Loop through the prototype chain looking for the function prototype.
   __ bind(&loop);
-  __ cmp(r2, Operand(r4));
+  __ cmp(scratch, Operand(prototype));
   __ b(eq, &is_instance);
   __ LoadRoot(ip, Heap::kNullValueRootIndex);
-  __ cmp(r2, ip);
+  __ cmp(scratch, ip);
   __ b(eq, &is_not_instance);
-  __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
-  __ ldr(r2, FieldMemOperand(r2, Map::kPrototypeOffset));
+  __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
+  __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
   __ jmp(&loop);
 
   __ bind(&is_instance);
   __ mov(r0, Operand(Smi::FromInt(0)));
   __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
-  __ pop();
-  __ pop();
-  __ mov(pc, Operand(lr));  // Return.
+  __ Ret(args_in_registers() ? 0 : 2);
 
   __ bind(&is_not_instance);
   __ mov(r0, Operand(Smi::FromInt(1)));
-  __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
-  __ pop();
-  __ pop();
-  __ mov(pc, Operand(lr));  // Return.
+  __ Ret(args_in_registers() ? 0 : 2);
+
+  Label object_not_null, object_not_null_or_smi;
+  __ bind(&not_js_object);
+  // Before null, smi and string value checks, check that the rhs is a function
+  // as for a non-function rhs an exception needs to be thrown.
+  __ BranchOnSmi(function, &slow);
+  __ CompareObjectType(function, map, scratch, JS_FUNCTION_TYPE);
+  __ b(ne, &slow);
+
+  // Null is not instance of anything.
+  __ cmp(scratch, Operand(Factory::null_value()));
+  __ b(ne, &object_not_null);
+  __ mov(r0, Operand(Smi::FromInt(1)));
+  __ Ret(args_in_registers() ? 0 : 2);
+
+  __ bind(&object_not_null);
+  // Smi values are not instances of anything.
+  __ BranchOnNotSmi(object, &object_not_null_or_smi);
+  __ mov(r0, Operand(Smi::FromInt(1)));
+  __ Ret(args_in_registers() ? 0 : 2);
+
+  __ bind(&object_not_null_or_smi);
+  // String values are not instances of anything.
+  __ IsObjectJSStringType(object, scratch, &slow);
+  __ mov(r0, Operand(Smi::FromInt(1)));
+  __ Ret(args_in_registers() ? 0 : 2);
 
   // Slow-case.  Tail call builtin.
   __ bind(&slow);
index 9c79231..e31d2e1 100644 (file)
@@ -1316,7 +1316,8 @@ LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
 
 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
   LInstruction* result =
-      new LInstanceOf(Use(instr->left()), Use(instr->right()));
+      new LInstanceOf(UseFixed(instr->left(), r1),
+                      UseFixed(instr->right(), r0));
   return MarkAsCall(DefineFixed(result, r0), instr);
 }
 
@@ -1375,6 +1376,12 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
     case kMathLog:
       Abort("MathLog LUnaryMathOperation not implemented");
       return NULL;
+    case kMathCos:
+      Abort("MathCos LUnaryMathOperation not implemented");
+      return NULL;
+    case kMathSin:
+      Abort("MathSin LUnaryMathOperation not implemented");
+      return NULL;
     default:
       UNREACHABLE();
       return NULL;
index 533d32c..dfc4891 100644 (file)
@@ -1337,7 +1337,14 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
 
 
 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
-  Abort("DoInstanceOf unimplemented.");
+  // We expect object and function in registers r1 and r0.
+  InstanceofStub stub(InstanceofStub::kArgsInRegisters);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+
+  Label true_value, done;
+  __ tst(r0, r0);
+  __ mov(r0, Operand(Factory::false_value()), LeaveCC, eq);
+  __ mov(r0, Operand(Factory::true_value()), LeaveCC, ne);
 }
 
 
@@ -1547,7 +1554,7 @@ void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) {
 
 
 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
-  Abort("LUnaryMathOperation unimplemented.");
+  Abort("DoMathAbs unimplemented.");
 }
 
 
@@ -1562,9 +1569,6 @@ void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) {
 
 
 void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
-  ASSERT(instr->op() == kMathFloor ||
-         instr->op() == kMathAbs);
-
   switch (instr->op()) {
     case kMathAbs:
       DoMathAbs(instr);
@@ -1576,6 +1580,7 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
       DoMathSqrt(instr);
       break;
     default:
+      Abort("Unimplemented type of LUnaryMathOperation.");
       UNREACHABLE();
   }
 }
index 6effec1..4a13146 100644 (file)
@@ -178,6 +178,12 @@ void MacroAssembler::Drop(int count, Condition cond) {
 }
 
 
+void MacroAssembler::Ret(int drop, Condition cond) {
+  Drop(drop, cond);
+  Ret(cond);
+}
+
+
 void MacroAssembler::Swap(Register reg1,
                           Register reg2,
                           Register scratch,
@@ -821,6 +827,38 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
 }
 
 
+void MacroAssembler::IsObjectJSObjectType(Register heap_object,
+                                          Register map,
+                                          Register scratch,
+                                          Label* fail) {
+  ldr(map, FieldMemOperand(heap_object, HeapObject::kMapOffset));
+  IsInstanceJSObjectType(map, scratch, fail);
+}
+
+
+void MacroAssembler::IsInstanceJSObjectType(Register map,
+                                            Register scratch,
+                                            Label* fail) {
+  ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
+  cmp(scratch, Operand(FIRST_JS_OBJECT_TYPE));
+  b(lt, fail);
+  cmp(scratch, Operand(LAST_JS_OBJECT_TYPE));
+  b(gt, fail);
+}
+
+
+void MacroAssembler::IsObjectJSStringType(Register object,
+                                           Register scratch,
+                                           Label* fail) {
+  ASSERT(kNotStringTag != 0);
+
+  ldr(scratch, FieldMemOperand(object, HeapObject::kMapOffset));
+  ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+  tst(scratch, Operand(kIsNotStringMask));
+  b(nz, fail);
+}
+
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
 void MacroAssembler::DebugBreak() {
   ASSERT(allow_stub_calls());
index 3da8726..97bbb2f 100644 (file)
@@ -96,6 +96,7 @@ class MacroAssembler: public Assembler {
   // from the stack, clobbering only the sp register.
   void Drop(int count, Condition cond = al);
 
+  void Ret(int drop, Condition cond = al);
 
   // Swap two registers.  If the scratch register is omitted then a slightly
   // less efficient form using xor instead of mov is emitted.
@@ -298,6 +299,18 @@ class MacroAssembler: public Assembler {
                       const ParameterCount& actual,
                       InvokeFlag flag);
 
+  void IsObjectJSObjectType(Register heap_object,
+                            Register map,
+                            Register scratch,
+                            Label* fail);
+
+  void IsInstanceJSObjectType(Register map,
+                              Register scratch,
+                              Label* fail);
+
+  void IsObjectJSStringType(Register object,
+                            Register scratch,
+                            Label* fail);
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // ---------------------------------------------------------------------------
index a805157..0f1e969 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -677,39 +677,76 @@ function ArraySort(comparefn) {
 
   function QuickSort(a, from, to) {
     // Insertion sort is faster for short arrays.
-    if (to - from <= 22) {
+    if (to - from <= 10) {
       InsertionSort(a, from, to);
       return;
     }
-    var pivot_index = $floor($random() * (to - from)) + from;
-    var pivot = a[pivot_index];
-    // Issue 95: Keep the pivot element out of the comparisons to avoid
-    // infinite recursion if comparefn(pivot, pivot) != 0.
-    %_SwapElements(a, from, pivot_index);
-    var low_end = from;   // Upper bound of the elements lower than pivot.
-    var high_start = to;  // Lower bound of the elements greater than pivot.
+    // Find a pivot as the median of first, last and middle element.
+    var v0 = a[from];
+    var v1 = a[to - 1];
+    var middle_index = from + ((to - from) >> 1);
+    var v2 = a[middle_index];
+    var c01 = %_CallFunction(global_receiver, v0, v1, comparefn);
+    if (c01 > 0) {
+      // v1 < v0, so swap them.
+      var tmp = v0;
+      v0 = v1;
+      v1 = tmp;
+    } // v0 <= v1.
+    var c02 = %_CallFunction(global_receiver, v0, v2, comparefn);
+    if (c02 >= 0) {
+      // v2 <= v0 <= v1.
+      var tmp = v0;
+      v0 = v2;
+      v2 = v1;
+      v1 = tmp;
+    } else {
+      // v0 <= v1 && v0 < v2
+      var c12 = %_CallFunction(global_receiver, v1, v2, comparefn);
+      if (c12 > 0) {
+        // v0 <= v2 < v1
+        var tmp = v1;
+        v1 = v2;
+        v2 = tmp;
+      }
+    }
+    // v0 <= v1 <= v2
+    a[from] = v0;
+    a[to - 1] = v2;
+    var pivot = v1;
+    var low_end = from + 1;   // Upper bound of elements lower than pivot.
+    var high_start = to - 1;  // Lower bound of elements greater than pivot.
+    a[middle_index] = a[low_end];
+    a[low_end] = pivot;
+
     // From low_end to i are elements equal to pivot.
     // From i to high_start are elements that haven't been compared yet.
-    for (var i = from + 1; i < high_start; ) {
+    partition: for (var i = low_end + 1; i < high_start; i++) {
       var element = a[i];
       var order = %_CallFunction(global_receiver, element, pivot, comparefn);
       if (order < 0) {
         %_SwapElements(a, i, low_end);
-        i++;
         low_end++;
       } else if (order > 0) {
-        high_start--;
+        do {
+          high_start--;
+          if (high_start == i) break partition;
+          var top_elem = a[high_start];
+          order = %_CallFunction(global_receiver, top_elem, pivot, comparefn);
+        } while (order > 0);
         %_SwapElements(a, i, high_start);
-      } else {  // order == 0
-        i++;
+        if (order < 0) {
+          %_SwapElements(a, i, low_end);
+          low_end++;
+        }
       }
     }
     QuickSort(a, from, low_end);
     QuickSort(a, high_start, to);
   }
 
-  // Copies elements in the range 0..length from obj's prototype chain
-  // to obj itself, if obj has holes. Returns one more than the maximal index
+  // Copy elements in the range 0..length from obj's prototype chain
+  // to obj itself, if obj has holes. Return one more than the maximal index
   // of a prototype property.
   function CopyFromPrototype(obj, length) {
     var max = 0;
index 3b44efa..eeb8412 100644 (file)
@@ -467,34 +467,35 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
 }
 
 
-void RelocInfo::Print() {
-  PrintF("%p  %s", pc_, RelocModeName(rmode_));
+void RelocInfo::Print(FILE* out) {
+  PrintF(out, "%p  %s", pc_, RelocModeName(rmode_));
   if (IsComment(rmode_)) {
-    PrintF("  (%s)", reinterpret_cast<char*>(data_));
+    PrintF(out, "  (%s)", reinterpret_cast<char*>(data_));
   } else if (rmode_ == EMBEDDED_OBJECT) {
-    PrintF("  (");
-    target_object()->ShortPrint();
-    PrintF(")");
+    PrintF(out, "  (");
+    target_object()->ShortPrint(out);
+    PrintF(out, ")");
   } else if (rmode_ == EXTERNAL_REFERENCE) {
     ExternalReferenceEncoder ref_encoder;
-    PrintF(" (%s)  (%p)",
+    PrintF(out, " (%s)  (%p)",
            ref_encoder.NameOfAddress(*target_reference_address()),
            *target_reference_address());
   } else if (IsCodeTarget(rmode_)) {
     Code* code = Code::GetCodeFromTargetAddress(target_address());
-    PrintF(" (%s)  (%p)", Code::Kind2String(code->kind()), target_address());
+    PrintF(out, " (%s)  (%p)", Code::Kind2String(code->kind()),
+           target_address());
   } else if (IsPosition(rmode_)) {
-    PrintF("  (%" V8_PTR_PREFIX "d)", data());
+    PrintF(out, "  (%" V8_PTR_PREFIX "d)", data());
   } else if (rmode_ == RelocInfo::RUNTIME_ENTRY) {
     // Depotimization bailouts are stored as runtime entries.
     int id = Deoptimizer::GetDeoptimizationId(
         target_address(), Deoptimizer::EAGER);
     if (id != Deoptimizer::kNotDeoptimizationEntry) {
-      PrintF("  (deoptimization bailout %d)", id);
+      PrintF(out, "  (deoptimization bailout %d)", id);
     }
   }
 
-  PrintF("\n");
+  PrintF(out, "\n");
 }
 #endif  // ENABLE_DISASSEMBLER
 
index 72a9b15..b68ad38 100644 (file)
@@ -322,7 +322,7 @@ class RelocInfo BASE_EMBEDDED {
 #ifdef ENABLE_DISASSEMBLER
   // Printing
   static const char* RelocModeName(Mode rmode);
-  void Print();
+  void Print(FILE* out);
 #endif  // ENABLE_DISASSEMBLER
 #ifdef DEBUG
   // Debugging
index a833119..21381f1 100644 (file)
@@ -515,10 +515,10 @@ BUILTIN(ArrayShift) {
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
         EnsureJSArrayWithWritableFastElements(receiver);
+    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
-  if (elms_obj == NULL ||
-      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+  if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArrayShift", args);
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
@@ -557,10 +557,10 @@ BUILTIN(ArrayUnshift) {
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
         EnsureJSArrayWithWritableFastElements(receiver);
+    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
-  if (elms_obj == NULL ||
-      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+  if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArrayUnshift", args);
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
@@ -611,21 +611,46 @@ BUILTIN(ArrayUnshift) {
 
 BUILTIN(ArraySlice) {
   Object* receiver = *args.receiver();
-  Object* elms_obj;
+  FixedArray* elms;
+  int len = -1;
   { MaybeObject* maybe_elms_obj =
         EnsureJSArrayWithWritableFastElements(receiver);
-    if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
-  }
-  if (elms_obj == NULL ||
-      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
-    return CallJsBuiltin("ArraySlice", args);
-  }
-  FixedArray* elms = FixedArray::cast(elms_obj);
-  JSArray* array = JSArray::cast(receiver);
-  ASSERT(array->HasFastElements());
-
-  int len = Smi::cast(array->length())->value();
+    Object* elms_obj;
+    if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) {
+      if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+        return CallJsBuiltin("ArraySlice", args);
+      }
+      elms = FixedArray::cast(elms_obj);
+      JSArray* array = JSArray::cast(receiver);
+      ASSERT(array->HasFastElements());
 
+      len = Smi::cast(array->length())->value();
+    } else {
+      // Array.slice(arguments, ...) is quite a common idiom (notably more
+      // than 50% of invocations in Web apps).  Treat it in C++ as well.
+      Map* arguments_map =
+          Top::context()->global_context()->arguments_boilerplate()->map();
+
+      bool is_arguments_object_with_fast_elements =
+          receiver->IsJSObject()
+          && JSObject::cast(receiver)->map() == arguments_map
+          && JSObject::cast(receiver)->HasFastElements();
+      if (!is_arguments_object_with_fast_elements) {
+        return CallJsBuiltin("ArraySlice", args);
+      }
+      elms = FixedArray::cast(JSObject::cast(receiver)->elements());
+      len = elms->length();
+#ifdef DEBUG
+      // Arguments object by construction should have no holes, check it.
+      if (FLAG_enable_slow_asserts) {
+        for (int i = 0; i < len; i++) {
+          ASSERT(elms->get(i) != Heap::the_hole_value());
+        }
+      }
+#endif
+    }
+  }
+  ASSERT(len >= 0);
   int n_arguments = args.length() - 1;
 
   // Note carefully choosen defaults---if argument is missing,
@@ -693,10 +718,10 @@ BUILTIN(ArraySplice) {
   Object* elms_obj;
   { MaybeObject* maybe_elms_obj =
         EnsureJSArrayWithWritableFastElements(receiver);
+    if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args);
     if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
   }
-  if (elms_obj == NULL ||
-      !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
+  if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
     return CallJsBuiltin("ArraySplice", args);
   }
   FixedArray* elms = FixedArray::cast(elms_obj);
index 8ba9971..b7804b7 100644 (file)
@@ -47,7 +47,7 @@ namespace internal {
   V(Compare)                             \
   V(CompareIC)                           \
   V(MathPow)                             \
-  V(TranscendentalCacheSSE2)             \
+  V(TranscendentalCache)                 \
   V(RecordWrite)                         \
   V(ConvertToDouble)                     \
   V(WriteInt32ToHeapNumber)              \
@@ -56,7 +56,6 @@ namespace internal {
   V(FastNewClosure)                      \
   V(FastNewContext)                      \
   V(FastCloneShallowArray)               \
-  V(TranscendentalCache)                 \
   V(GenericUnaryOp)                      \
   V(RevertToNumber)                      \
   V(ToBoolean)                           \
index 8a64d77..da479e8 100644 (file)
@@ -215,8 +215,17 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
       }
       PrintF("\n\n");
     }
-    PrintF("--- Code ---\n");
-    code->Disassemble(*function->name()->ToCString());
+    if (info->IsOptimizing()) {
+      if (FLAG_print_unopt_code) {
+        PrintF("--- Unoptimized code ---\n");
+        info->closure()->shared()->code()->Disassemble(
+            *function->debug_name()->ToCString());
+      }
+      PrintF("--- Optimized code ---\n");
+    } else {
+      PrintF("--- Code ---\n");
+    }
+    code->Disassemble(*function->debug_name()->ToCString());
   }
 #endif  // ENABLE_DISASSEMBLER
 }
index aed46cf..048fdaa 100644 (file)
@@ -28,6 +28,9 @@
 #ifndef V8_COUNTERS_H_
 #define V8_COUNTERS_H_
 
+#include "../include/v8.h"
+#include "allocation.h"
+
 namespace v8 {
 namespace internal {
 
index 38bb8eb..bc70327 100644 (file)
@@ -1007,6 +1007,39 @@ function DateToJSON(key) {
 }
 
 
+function ResetDateCache() {
+
+  // Reset the local_time_offset:
+  local_time_offset = %DateLocalTimeOffset();
+
+  // Reset the DST offset cache:
+  var cache = DST_offset_cache;
+  cache.offset = 0;
+  cache.start = 0;
+  cache.end = -1;
+  cache.increment = 0;
+  cache.initial_increment = 19 * msPerDay;
+
+  // Reset the timezone cache:
+  timezone_cache_time = $NaN;
+  timezone_cache_timezone = undefined;
+
+  // Reset the ltcache:
+  ltcache.key = null;
+  ltcache.val = null;
+
+  // Reset the ymd_from_time_cache:
+  ymd_from_time_cache = [$NaN, $NaN, $NaN];
+  ymd_from_time_cached_time = $NaN;
+
+  // Reset the date cache:
+  cache = Date_cache;
+  cache.time = $NaN;
+  cache.year = $NaN;
+  cache.string = null;
+}
+
+
 // -------------------------------------------------------------------
 
 function SetupDate() {
index 7709eb0..ca3c1db 100644 (file)
@@ -858,7 +858,7 @@ bool Debug::Load() {
   if (caught_exception) return false;
 
   // Debugger loaded.
-  debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
+  debug_context_ = context;
 
   return true;
 }
index 93839a4..dd70baa 100644 (file)
@@ -1096,7 +1096,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) {
 }
 
 
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
 
 const char* Translation::StringFor(Opcode opcode) {
   switch (opcode) {
index 32edd10..2d7dfc8 100644 (file)
@@ -476,7 +476,7 @@ class Translation BASE_EMBEDDED {
 
   static int NumberOfOperandsFor(Opcode opcode);
 
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   static const char* StringFor(Opcode opcode);
 #endif
 
index facbec2..f160a85 100644 (file)
@@ -296,6 +296,9 @@ DEFINE_int(max_map_space_pages, MapSpace::kMaxMapPageIndex - 1,
 DEFINE_bool(h, false, "print this message")
 DEFINE_bool(new_snapshot, true, "use new snapshot implementation")
 
+// objects.cc
+DEFINE_bool(use_verbose_printer, true, "allows verbose printing")
+
 // parser.cc
 DEFINE_bool(allow_natives_syntax, false, "allow natives syntax")
 
@@ -503,6 +506,8 @@ DEFINE_bool(print_code_stubs, false, "print code stubs")
 // codegen-ia32.cc / codegen-arm.cc
 DEFINE_bool(print_code, false, "print generated code")
 DEFINE_bool(print_opt_code, false, "print optimized code")
+DEFINE_bool(print_unopt_code, false, "print unoptimized code before "
+            "printing optimized code based on it")
 DEFINE_bool(print_code_verbose, false, "print more information for code")
 DEFINE_bool(print_builtin_code, false, "print generated code for builtins")
 
index 96307a3..58540f0 100644 (file)
@@ -671,8 +671,12 @@ const FullCodeGenerator::InlineFunctionGenerator
 
 FullCodeGenerator::InlineFunctionGenerator
   FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
-    return kInlineFunctionGenerators[
-      static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)];
+    int lookup_index =
+        static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
+    ASSERT(lookup_index >= 0);
+    ASSERT(static_cast<size_t>(lookup_index) <
+           ARRAY_SIZE(kInlineFunctionGenerators));
+    return kInlineFunctionGenerators[lookup_index];
 }
 
 
@@ -684,7 +688,6 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
   ASSERT(function->intrinsic_type == Runtime::INLINE);
   InlineFunctionGenerator generator =
       FindInlineFunctionGenerator(function->function_id);
-  ASSERT(generator != NULL);
   ((*this).*(generator))(args);
 }
 
index 0029500..dfda7c6 100644 (file)
@@ -367,7 +367,6 @@ HeapSnapshot* HeapProfiler::TakeSnapshot(String* name,
 HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
                                              int type,
                                              v8::ActivityControl* control) {
-  Heap::CollectAllGarbage(true);
   HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type);
   HeapSnapshot* result =
       snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++);
@@ -379,6 +378,7 @@ HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
       break;
     }
     case HeapSnapshot::kAggregated: {
+      Heap::CollectAllGarbage(true);
       AggregatedHeapSnapshot agg_snapshot;
       AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
       generator.GenerateSnapshot();
@@ -808,7 +808,7 @@ void AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
 
 
 void AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
-  HeapIterator iterator(HeapIterator::kPreciseFiltering);
+  HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
   for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
     CollectStats(obj);
     agg_snapshot_->js_cons_profile()->CollectStats(obj);
index ccf9b47..1e99991 100644 (file)
@@ -4483,7 +4483,7 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
       MemoryAllocator::Size() + MemoryAllocator::Available();
   *stats->os_error = OS::GetLastError();
   if (take_snapshot) {
-    HeapIterator iterator(HeapIterator::kPreciseFiltering);
+    HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
     for (HeapObject* obj = iterator.next();
          obj != NULL;
          obj = iterator.next()) {
@@ -4917,13 +4917,20 @@ ObjectIterator* SpaceIterator::CreateIterator() {
 }
 
 
-class FreeListNodesFilter {
+class HeapObjectsFilter {
+ public:
+  virtual ~HeapObjectsFilter() {}
+  virtual bool SkipObject(HeapObject* object) = 0;
+};
+
+
+class FreeListNodesFilter : public HeapObjectsFilter {
  public:
   FreeListNodesFilter() {
     MarkFreeListNodes();
   }
 
-  inline bool IsFreeListNode(HeapObject* object) {
+  bool SkipObject(HeapObject* object) {
     if (object->IsMarked()) {
       object->ClearMark();
       return true;
@@ -4955,6 +4962,65 @@ class FreeListNodesFilter {
 };
 
 
+class UnreachableObjectsFilter : public HeapObjectsFilter {
+ public:
+  UnreachableObjectsFilter() {
+    MarkUnreachableObjects();
+  }
+
+  bool SkipObject(HeapObject* object) {
+    if (object->IsMarked()) {
+      object->ClearMark();
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+ private:
+  class UnmarkingVisitor : public ObjectVisitor {
+   public:
+    UnmarkingVisitor() : list_(10) {}
+
+    void VisitPointers(Object** start, Object** end) {
+      for (Object** p = start; p < end; p++) {
+        if (!(*p)->IsHeapObject()) continue;
+        HeapObject* obj = HeapObject::cast(*p);
+        if (obj->IsMarked()) {
+          obj->ClearMark();
+          list_.Add(obj);
+        }
+      }
+    }
+
+    bool can_process() { return !list_.is_empty(); }
+
+    void ProcessNext() {
+      HeapObject* obj = list_.RemoveLast();
+      obj->Iterate(this);
+    }
+
+   private:
+    List<HeapObject*> list_;
+  };
+
+  void MarkUnreachableObjects() {
+    HeapIterator iterator;
+    for (HeapObject* obj = iterator.next();
+         obj != NULL;
+         obj = iterator.next()) {
+      obj->SetMark();
+    }
+    UnmarkingVisitor visitor;
+    Heap::IterateRoots(&visitor, VISIT_ONLY_STRONG);
+    while (visitor.can_process())
+      visitor.ProcessNext();
+  }
+
+  AssertNoAllocation no_alloc;
+};
+
+
 HeapIterator::HeapIterator()
     : filtering_(HeapIterator::kNoFiltering),
       filter_(NULL) {
@@ -4962,7 +5028,7 @@ HeapIterator::HeapIterator()
 }
 
 
-HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering)
+HeapIterator::HeapIterator(HeapIterator::HeapObjectsFiltering filtering)
     : filtering_(filtering),
       filter_(NULL) {
   Init();
@@ -4976,12 +5042,17 @@ HeapIterator::~HeapIterator() {
 
 void HeapIterator::Init() {
   // Start the iteration.
-  if (filtering_ == kPreciseFiltering) {
-    filter_ = new FreeListNodesFilter;
-    space_iterator_ =
-        new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
-  } else {
-    space_iterator_ = new SpaceIterator;
+  space_iterator_ = filtering_ == kNoFiltering ? new SpaceIterator :
+      new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
+  switch (filtering_) {
+    case kFilterFreeListNodes:
+      filter_ = new FreeListNodesFilter;
+      break;
+    case kFilterUnreachable:
+      filter_ = new UnreachableObjectsFilter;
+      break;
+    default:
+      break;
   }
   object_iterator_ = space_iterator_->next();
 }
@@ -4989,9 +5060,9 @@ void HeapIterator::Init() {
 
 void HeapIterator::Shutdown() {
 #ifdef DEBUG
-  // Assert that in precise mode we have iterated through all
+  // Assert that in filtering mode we have iterated through all
   // objects. Otherwise, heap will be left in an inconsistent state.
-  if (filtering_ == kPreciseFiltering) {
+  if (filtering_ != kNoFiltering) {
     ASSERT(object_iterator_ == NULL);
   }
 #endif
@@ -5008,7 +5079,7 @@ HeapObject* HeapIterator::next() {
   if (filter_ == NULL) return NextObject();
 
   HeapObject* obj = NextObject();
-  while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject();
+  while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
   return obj;
 }
 
index fbcc70d..18a4afb 100644 (file)
@@ -1585,17 +1585,18 @@ class SpaceIterator : public Malloced {
 // nodes filtering uses GC marks, it can't be used during MS/MC GC
 // phases. Also, it is forbidden to interrupt iteration in this mode,
 // as this will leave heap objects marked (and thus, unusable).
-class FreeListNodesFilter;
+class HeapObjectsFilter;
 
 class HeapIterator BASE_EMBEDDED {
  public:
-  enum FreeListNodesFiltering {
+  enum HeapObjectsFiltering {
     kNoFiltering,
-    kPreciseFiltering
+    kFilterFreeListNodes,
+    kFilterUnreachable
   };
 
   HeapIterator();
-  explicit HeapIterator(FreeListNodesFiltering filtering);
+  explicit HeapIterator(HeapObjectsFiltering filtering);
   ~HeapIterator();
 
   HeapObject* next();
@@ -1608,8 +1609,8 @@ class HeapIterator BASE_EMBEDDED {
   void Shutdown();
   HeapObject* NextObject();
 
-  FreeListNodesFiltering filtering_;
-  FreeListNodesFilter* filter_;
+  HeapObjectsFiltering filtering_;
+  HeapObjectsFilter* filter_;
   // Space iterator for iterating all the spaces.
   SpaceIterator* space_iterator_;
   // Object iterator for the space currently being iterated.
@@ -1968,6 +1969,8 @@ class GCTracer BASE_EMBEDDED {
 class TranscendentalCache {
  public:
   enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches};
+  static const int kTranscendentalTypeBits = 3;
+  STATIC_ASSERT((1 << kTranscendentalTypeBits) >= kNumberOfCaches);
 
   explicit TranscendentalCache(Type t);
 
@@ -2056,7 +2059,6 @@ class TranscendentalCache {
   friend class ExternalReference;
   // Inline implementation of the cache.
   friend class TranscendentalCacheStub;
-  friend class TranscendentalCacheSSE2Stub;
 
   static TranscendentalCache* caches_[kNumberOfCaches];
   Element elements_[kCacheSize];
index a96ee40..3f39888 100644 (file)
@@ -579,6 +579,13 @@ void HBranch::PrintDataTo(StringStream* stream) const {
 }
 
 
+void HCompareMapAndBranch::PrintDataTo(StringStream* stream) const {
+  stream->Add("on ");
+  value()->PrintNameTo(stream);
+  stream->Add(" (%p)", *map());
+}
+
+
 void HGoto::PrintDataTo(StringStream* stream) const {
   stream->Add("B%d", FirstSuccessor()->block_id());
 }
index aafa7a8..cbbe8fc 100644 (file)
@@ -905,6 +905,8 @@ class HCompareMapAndBranch: public HUnaryControlInstruction {
   virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
   virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
 
+  virtual void PrintDataTo(StringStream* stream) const;
+
   Handle<Map> map() const { return map_; }
 
   DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
@@ -1387,6 +1389,8 @@ class HUnaryMathOperation: public HUnaryOperation {
       case kMathSqrt:
       case kMathPowHalf:
       case kMathLog:
+      case kMathSin:
+      case kMathCos:
         set_representation(Representation::Double());
         break;
       default:
@@ -1409,6 +1413,8 @@ class HUnaryMathOperation: public HUnaryOperation {
       case kMathSqrt:
       case kMathPowHalf:
       case kMathLog:
+      case kMathSin:
+      case kMathCos:
         return Representation::Double();
         break;
       case kMathAbs:
index 32108dc..e34acd6 100644 (file)
@@ -3165,6 +3165,9 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
   if (lookup->type() == MAP_TRANSITION) {
     Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
     instr->set_transition(transition);
+    // TODO(fschneider): Record the new map type of the object in the IR to
+    // enable elimination of redundant checks after the transition store.
+    instr->SetFlag(HValue::kChangesMaps);
   }
   return instr;
 }
@@ -3529,9 +3532,10 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
       maps.Add(map);
       HSubgraph* subgraph = CreateBranchSubgraph(environment());
       SubgraphScope scope(this, subgraph);
-      HInstruction* instr =
+      HLoadNamedField* instr =
           BuildLoadNamedField(object, expr, map, &lookup, false);
       instr->set_position(expr->position());
+      instr->ClearFlag(HValue::kUseGVN);  // Don't do GVN on polymorphic loads.
       PushAndAdd(instr);
       subgraphs.Add(subgraph);
     } else {
@@ -3570,11 +3574,11 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
 }
 
 
-HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object,
-                                                 Property* expr,
-                                                 Handle<Map> type,
-                                                 LookupResult* lookup,
-                                                 bool smi_and_map_check) {
+HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
+                                                    Property* expr,
+                                                    Handle<Map> type,
+                                                    LookupResult* lookup,
+                                                    bool smi_and_map_check) {
   if (smi_and_map_check) {
     AddInstruction(new HCheckNonSmi(object));
     AddInstruction(new HCheckMap(object, type));
@@ -4093,6 +4097,8 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
     case kMathAbs:
     case kMathSqrt:
     case kMathLog:
+    case kMathSin:
+    case kMathCos:
       if (argument_count == 2) {
         HValue* argument = Pop();
         Drop(1);  // Receiver.
@@ -4169,7 +4175,7 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
   if (args->length() != 2) return false;
 
   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
-  if (arg_two == NULL) return false;
+  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
   HValue* arg_two_value = environment()->Lookup(arg_two->var());
   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
 
index 2c9aeac..ebabf3d 100644 (file)
@@ -786,11 +786,11 @@ class HGraphBuilder: public AstVisitor {
                                      HValue* left,
                                      HValue* right);
   HInstruction* BuildIncrement(HValue* value, bool increment);
-  HInstruction* BuildLoadNamedField(HValue* object,
-                                    Property* expr,
-                                    Handle<Map> type,
-                                    LookupResult* result,
-                                    bool smi_and_map_check);
+  HLoadNamedField* BuildLoadNamedField(HValue* object,
+                                       Property* expr,
+                                       Handle<Map> type,
+                                       LookupResult* result,
+                                       bool smi_and_map_check);
   HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr);
   HInstruction* BuildLoadKeyedFastElement(HValue* object,
                                           HValue* key,
index d75acab..a371c96 100644 (file)
@@ -2472,41 +2472,65 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
 
 
 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
-  // Input on stack:
-  // esp[4]: argument (should be number).
-  // esp[0]: return address.
-  // Test that eax is a number.
+  // TAGGED case:
+  //   Input:
+  //     esp[4]: tagged number input argument (should be number).
+  //     esp[0]: return address.
+  //   Output:
+  //     eax: tagged double result.
+  // UNTAGGED case:
+  //   Input::
+  //     esp[0]: return address.
+  //     xmm1: untagged double input argument
+  //   Output:
+  //     xmm1: untagged double result.
+
   Label runtime_call;
   Label runtime_call_clear_stack;
-  NearLabel input_not_smi;
-  NearLabel loaded;
-  __ mov(eax, Operand(esp, kPointerSize));
-  __ test(eax, Immediate(kSmiTagMask));
-  __ j(not_zero, &input_not_smi);
-  // Input is a smi. Untag and load it onto the FPU stack.
-  // Then load the low and high words of the double into ebx, edx.
-  STATIC_ASSERT(kSmiTagSize == 1);
-  __ sar(eax, 1);
-  __ sub(Operand(esp), Immediate(2 * kPointerSize));
-  __ mov(Operand(esp, 0), eax);
-  __ fild_s(Operand(esp, 0));
-  __ fst_d(Operand(esp, 0));
-  __ pop(edx);
-  __ pop(ebx);
-  __ jmp(&loaded);
-  __ bind(&input_not_smi);
-  // Check if input is a HeapNumber.
-  __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
-  __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
-  __ j(not_equal, &runtime_call);
-  // Input is a HeapNumber. Push it on the FPU stack and load its
-  // low and high words into ebx, edx.
-  __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
-  __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
-  __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
+  Label skip_cache;
+  const bool tagged = (argument_type_ == TAGGED);
+  if (tagged) {
+    // Test that eax is a number.
+    NearLabel input_not_smi;
+    NearLabel loaded;
+    __ mov(eax, Operand(esp, kPointerSize));
+    __ test(eax, Immediate(kSmiTagMask));
+    __ j(not_zero, &input_not_smi);
+    // Input is a smi. Untag and load it onto the FPU stack.
+    // Then load the low and high words of the double into ebx, edx.
+    STATIC_ASSERT(kSmiTagSize == 1);
+    __ sar(eax, 1);
+    __ sub(Operand(esp), Immediate(2 * kPointerSize));
+    __ mov(Operand(esp, 0), eax);
+    __ fild_s(Operand(esp, 0));
+    __ fst_d(Operand(esp, 0));
+    __ pop(edx);
+    __ pop(ebx);
+    __ jmp(&loaded);
+    __ bind(&input_not_smi);
+    // Check if input is a HeapNumber.
+    __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
+    __ cmp(Operand(ebx), Immediate(Factory::heap_number_map()));
+    __ j(not_equal, &runtime_call);
+    // Input is a HeapNumber. Push it on the FPU stack and load its
+    // low and high words into ebx, edx.
+    __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
+    __ mov(edx, FieldOperand(eax, HeapNumber::kExponentOffset));
+    __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
+
+    __ bind(&loaded);
+  } else {  // UNTAGGED.
+    if (CpuFeatures::IsSupported(SSE4_1)) {
+      CpuFeatures::Scope sse4_scope(SSE4_1);
+      __ pextrd(Operand(edx), xmm1, 0x1);  // copy xmm1[63..32] to edx.
+    } else {
+      __ pshufd(xmm0, xmm1, 0x1);
+      __ movd(Operand(edx), xmm0);
+    }
+    __ movd(Operand(ebx), xmm1);
+  }
 
-  __ bind(&loaded);
-  // ST[0] == double value
+  // ST[0] or xmm1  == double value
   // ebx = low 32 bits of double value
   // edx = high 32 bits of double value
   // Compute hash (the shifts are arithmetic):
@@ -2522,7 +2546,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
   ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
   __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
 
-  // ST[0] == double value.
+  // ST[0] or xmm1 == double value.
   // ebx = low 32 bits of double value.
   // edx = high 32 bits of double value.
   // ecx = TranscendentalCache::hash(double value).
@@ -2559,31 +2583,80 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
   __ j(not_equal, &cache_miss);
   // Cache hit!
   __ mov(eax, Operand(ecx, 2 * kIntSize));
-  __ fstp(0);
-  __ ret(kPointerSize);
+  if (tagged) {
+    __ fstp(0);
+    __ ret(kPointerSize);
+  } else {  // UNTAGGED.
+    __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+    __ Ret();
+  }
 
   __ bind(&cache_miss);
   // Update cache with new value.
   // We are short on registers, so use no_reg as scratch.
   // This gives slightly larger code.
-  __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
+  if (tagged) {
+    __ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack);
+  } else {  // UNTAGGED.
+    __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
+    __ sub(Operand(esp), Immediate(kDoubleSize));
+    __ movdbl(Operand(esp, 0), xmm1);
+    __ fld_d(Operand(esp, 0));
+    __ add(Operand(esp), Immediate(kDoubleSize));
+  }
   GenerateOperation(masm);
   __ mov(Operand(ecx, 0), ebx);
   __ mov(Operand(ecx, kIntSize), edx);
   __ mov(Operand(ecx, 2 * kIntSize), eax);
   __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
-  __ ret(kPointerSize);
+  if (tagged) {
+    __ ret(kPointerSize);
+  } else {  // UNTAGGED.
+    __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+    __ Ret();
+
+    // Skip cache and return answer directly, only in untagged case.
+    __ bind(&skip_cache);
+    __ sub(Operand(esp), Immediate(kDoubleSize));
+    __ movdbl(Operand(esp, 0), xmm1);
+    __ fld_d(Operand(esp, 0));
+    GenerateOperation(masm);
+    __ fstp_d(Operand(esp, 0));
+    __ movdbl(xmm1, Operand(esp, 0));
+    __ add(Operand(esp), Immediate(kDoubleSize));
+    // We return the value in xmm1 without adding it to the cache, but
+    // we cause a scavenging GC so that future allocations will succeed.
+    __ EnterInternalFrame();
+    // Allocate an unused object bigger than a HeapNumber.
+    __ push(Immediate(Smi::FromInt(2 * kDoubleSize)));
+    __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
+    __ LeaveInternalFrame();
+    __ Ret();
+  }
 
-  __ bind(&runtime_call_clear_stack);
-  __ fstp(0);
-  __ bind(&runtime_call);
-  __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+  // Call runtime, doing whatever allocation and cleanup is necessary.
+  if (tagged) {
+    __ bind(&runtime_call_clear_stack);
+    __ fstp(0);
+    __ bind(&runtime_call);
+    __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
+  } else {  // UNTAGGED.
+    __ bind(&runtime_call_clear_stack);
+    __ bind(&runtime_call);
+    __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
+    __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
+    __ EnterInternalFrame();
+    __ push(eax);
+    __ CallRuntime(RuntimeFunction(), 1);
+    __ LeaveInternalFrame();
+    __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+    __ Ret();
+  }
 }
 
 
 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
   switch (type_) {
-    // Add more cases when necessary.
     case TranscendentalCache::SIN: return Runtime::kMath_sin;
     case TranscendentalCache::COS: return Runtime::kMath_cos;
     case TranscendentalCache::LOG: return Runtime::kMath_log;
@@ -2596,14 +2669,14 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
 
 void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
   // Only free register is edi.
-  // Input value is on FP stack, and also in ebx/edx.  Address of result
-  // (a newly allocated HeapNumber) is in eax.
-  NearLabel done;
+  // Input value is on FP stack, and also in ebx/edx.
+  // Input value is possibly in xmm1.
+  // Address of result (a newly allocated HeapNumber) may be in eax.
   if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
     // Both fsin and fcos require arguments in the range +/-2^63 and
     // return NaN for infinities and NaN. They can share all code except
     // the actual fsin/fcos operation.
-    NearLabel in_range;
+    NearLabel in_range, done;
     // If argument is outside the range -2^63..2^63, fsin/cos doesn't
     // work. We must reduce it to the appropriate range.
     __ mov(edi, edx);
@@ -2683,145 +2756,6 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
 }
 
 
-void TranscendentalCacheSSE2Stub::Generate(MacroAssembler* masm) {
-  // Input on stack:
-  // esp[0]: return address.
-  // Input in registers:
-  // xmm1:   untagged double input argument.
-  // Output:
-  // xmm1:   untagged double result.
-  Label skip_cache;
-  Label call_runtime;
-
-  // Input is an untagged double in xmm1.
-  // Compute hash (the shifts are arithmetic):
-  //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
-  if (CpuFeatures::IsSupported(SSE4_1)) {
-    CpuFeatures::Scope sse4_scope(SSE4_1);
-    __ pextrd(Operand(edx), xmm1, 0x1);  // copy xmm1[63..32] to edx.
-  } else {
-    __ pshufd(xmm0, xmm1, 0x1);
-    __ movd(Operand(edx), xmm0);
-  }
-  __ movd(Operand(ebx), xmm1);
-
-  // xmm1 = double value
-  // ebx = low 32 bits of double value
-  // edx = high 32 bits of double value
-  // Compute hash (the shifts are arithmetic):
-  //   h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
-  __ mov(ecx, ebx);
-  __ xor_(ecx, Operand(edx));
-  __ mov(eax, ecx);
-  __ sar(eax, 16);
-  __ xor_(ecx, Operand(eax));
-  __ mov(eax, ecx);
-  __ sar(eax, 8);
-  __ xor_(ecx, Operand(eax));
-  ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
-  __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
-
-  // xmm1 = double value.
-  // ebx = low 32 bits of double value.
-  // edx = high 32 bits of double value.
-  // ecx = TranscendentalCache::hash(double value).
-  __ mov(eax,
-         Immediate(ExternalReference::transcendental_cache_array_address()));
-  // Eax points to cache array.
-  __ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
-  // Eax points to the cache for the type type_.
-  // If NULL, the cache hasn't been initialized yet, so go through runtime.
-  __ test(eax, Operand(eax));
-  __ j(zero, &call_runtime);
-#ifdef DEBUG
-  // Check that the layout of cache elements match expectations.
-  { TranscendentalCache::Element test_elem[2];
-    char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
-    char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
-    char* elem_in0  = reinterpret_cast<char*>(&(test_elem[0].in[0]));
-    char* elem_in1  = reinterpret_cast<char*>(&(test_elem[0].in[1]));
-    char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
-    CHECK_EQ(12, elem2_start - elem_start);  // Two uint_32's and a pointer.
-    CHECK_EQ(0, elem_in0 - elem_start);
-    CHECK_EQ(kIntSize, elem_in1 - elem_start);
-    CHECK_EQ(2 * kIntSize, elem_out - elem_start);
-  }
-#endif
-  // Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
-  __ lea(ecx, Operand(ecx, ecx, times_2, 0));
-  __ lea(ecx, Operand(eax, ecx, times_4, 0));
-  // Check if cache matches: Double value is stored in uint32_t[2] array.
-  NearLabel cache_miss;
-  __ cmp(ebx, Operand(ecx, 0));
-  __ j(not_equal, &cache_miss);
-  __ cmp(edx, Operand(ecx, kIntSize));
-  __ j(not_equal, &cache_miss);
-  // Cache hit!
-  __ mov(eax, Operand(ecx, 2 * kIntSize));
-  __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
-  __ Ret();
-
-  __ bind(&cache_miss);
-  // Update cache with new value.
-  // We are short on registers, so use no_reg as scratch.
-  // This gives slightly larger code.
-  __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
-  __ sub(Operand(esp), Immediate(kDoubleSize));
-  __ movdbl(Operand(esp, 0), xmm1);
-  __ fld_d(Operand(esp, 0));
-  __ add(Operand(esp), Immediate(kDoubleSize));
-  GenerateOperation(masm);
-  __ mov(Operand(ecx, 0), ebx);
-  __ mov(Operand(ecx, kIntSize), edx);
-  __ mov(Operand(ecx, 2 * kIntSize), eax);
-  __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
-  __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
-  __ Ret();
-
-  __ bind(&skip_cache);
-  __ sub(Operand(esp), Immediate(kDoubleSize));
-  __ movdbl(Operand(esp, 0), xmm1);
-  __ fld_d(Operand(esp, 0));
-  GenerateOperation(masm);
-  __ fstp_d(Operand(esp, 0));
-  __ movdbl(xmm1, Operand(esp, 0));
-  __ add(Operand(esp), Immediate(kDoubleSize));
-  __ Ret();
-
-  __ bind(&call_runtime);
-  __ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
-  __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
-  __ EnterInternalFrame();
-  __ push(eax);
-  __ CallRuntime(RuntimeFunction(), 1);
-  __ LeaveInternalFrame();
-  __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
-  __ Ret();
-}
-
-
-Runtime::FunctionId TranscendentalCacheSSE2Stub::RuntimeFunction() {
-  switch (type_) {
-    // Add more cases when necessary.
-    case TranscendentalCache::LOG: return Runtime::kMath_log;
-    default:
-      UNIMPLEMENTED();
-      return Runtime::kAbort;
-  }
-}
-
-
-void TranscendentalCacheSSE2Stub::GenerateOperation(MacroAssembler* masm) {
-  // Only free register is edi.
-  // Input value is on FP stack and in xmm1.
-
-  ASSERT(type_ == TranscendentalCache::LOG);
-  __ fldln2();
-  __ fxch();
-  __ fyl2x();
-}
-
-
 // Get the integer part of a heap number.  Surprisingly, all this bit twiddling
 // is faster than using the built-in instructions on floating point registers.
 // Trashes edi and ebx.  Dest is ecx.  Source cannot be ecx or one of the
index 04f23ac..f66a8c7 100644 (file)
@@ -40,32 +40,21 @@ namespace internal {
 // TranscendentalCache runtime function.
 class TranscendentalCacheStub: public CodeStub {
  public:
-  explicit TranscendentalCacheStub(TranscendentalCache::Type type)
-      : type_(type) {}
-  void Generate(MacroAssembler* masm);
- private:
-  TranscendentalCache::Type type_;
-
-  Major MajorKey() { return TranscendentalCache; }
-  int MinorKey() { return type_; }
-  Runtime::FunctionId RuntimeFunction();
-  void GenerateOperation(MacroAssembler* masm);
-};
-
+  enum ArgumentType {
+    TAGGED = 0,
+    UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
+  };
 
-// Check the transcendental cache, or generate the result, using SSE2.
-// The argument and result will be in xmm1.
-// Only supports TranscendentalCache::LOG at this point.
-class TranscendentalCacheSSE2Stub: public CodeStub {
- public:
-  explicit TranscendentalCacheSSE2Stub(TranscendentalCache::Type type)
-      : type_(type) {}
+  explicit TranscendentalCacheStub(TranscendentalCache::Type type,
+                                   ArgumentType argument_type)
+      : type_(type), argument_type_(argument_type) {}
   void Generate(MacroAssembler* masm);
  private:
   TranscendentalCache::Type type_;
+  ArgumentType argument_type_;
 
-  Major MajorKey() { return TranscendentalCacheSSE2; }
-  int MinorKey() { return type_; }
+  Major MajorKey() { return TranscendentalCache; }
+  int MinorKey() { return type_ | argument_type_; }
   Runtime::FunctionId RuntimeFunction();
   void GenerateOperation(MacroAssembler* masm);
 };
index 4c9d055..2f14e82 100644 (file)
@@ -7912,7 +7912,8 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  TranscendentalCacheStub stub(TranscendentalCache::SIN);
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::TAGGED);
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
@@ -7921,7 +7922,8 @@ void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  TranscendentalCacheStub stub(TranscendentalCache::COS);
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::TAGGED);
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
@@ -7930,7 +7932,8 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
 void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
   ASSERT_EQ(args->length(), 1);
   Load(args->at(0));
-  TranscendentalCacheStub stub(TranscendentalCache::LOG);
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::TAGGED);
   Result result = frame_->CallStub(&stub, 1);
   frame_->Push(&result);
 }
index be059cd..13a1177 100644 (file)
@@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
 
 void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
   // Load the argument on the stack and call the stub.
-  TranscendentalCacheStub stub(TranscendentalCache::SIN);
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
   __ CallStub(&stub);
@@ -3077,7 +3078,8 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
 
 void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
   // Load the argument on the stack and call the stub.
-  TranscendentalCacheStub stub(TranscendentalCache::COS);
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
   __ CallStub(&stub);
@@ -3087,7 +3089,8 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
 
 void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
   // Load the argument on the stack and call the stub.
-  TranscendentalCacheStub stub(TranscendentalCache::LOG);
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::TAGGED);
   ASSERT(args->length() == 1);
   VisitForStackValue(args->at(0));
   __ CallStub(&stub);
index 0e97737..d64f528 100644 (file)
@@ -686,7 +686,8 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
       break;
     }
     case CodeStub::TranscendentalCache: {
-      TranscendentalCacheStub stub(instr->transcendental_type());
+      TranscendentalCacheStub stub(instr->transcendental_type(),
+                                   TranscendentalCacheStub::TAGGED);
       CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
       break;
     }
@@ -2314,7 +2315,24 @@ void LCodeGen::DoPower(LPower* instr) {
 
 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
   ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
-  TranscendentalCacheSSE2Stub stub(TranscendentalCache::LOG);
+  TranscendentalCacheStub stub(TranscendentalCache::LOG,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathCos(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+  TranscendentalCacheStub stub(TranscendentalCache::COS,
+                               TranscendentalCacheStub::UNTAGGED);
+  CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+}
+
+
+void LCodeGen::DoMathSin(LUnaryMathOperation* instr) {
+  ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
+  TranscendentalCacheStub stub(TranscendentalCache::SIN,
+                               TranscendentalCacheStub::UNTAGGED);
   CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
 }
 
@@ -2336,6 +2354,12 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
     case kMathPowHalf:
       DoMathPowHalf(instr);
       break;
+    case kMathCos:
+      DoMathCos(instr);
+      break;
+    case kMathSin:
+      DoMathSin(instr);
+      break;
     case kMathLog:
       DoMathLog(instr);
       break;
index 5ac7b1e..6d8173a 100644 (file)
@@ -177,6 +177,8 @@ class LCodeGen BASE_EMBEDDED {
   void DoMathSqrt(LUnaryMathOperation* instr);
   void DoMathPowHalf(LUnaryMathOperation* instr);
   void DoMathLog(LUnaryMathOperation* instr);
+  void DoMathCos(LUnaryMathOperation* instr);
+  void DoMathSin(LUnaryMathOperation* instr);
 
   // Support for recording safepoint and position information.
   void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);
index e1148fc..3b272d0 100644 (file)
@@ -1361,7 +1361,7 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
 
 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
   BuiltinFunctionId op = instr->op();
-  if (op == kMathLog) {
+  if (op == kMathLog || op == kMathSin || op == kMathCos) {
     LOperand* input = UseFixedDouble(instr->value(), xmm1);
     LInstruction* result = new LUnaryMathOperation(input);
     return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
index cb7b35e..53296d9 100644 (file)
 namespace v8 {
 namespace internal {
 
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
 
 static const char* TypeToString(InstanceType type);
 
 
-void MaybeObject::Print() {
+void MaybeObject::Print(FILE* out) {
   Object* this_as_object;
   if (ToObject(&this_as_object)) {
     if (this_as_object->IsSmi()) {
-      Smi::cast(this_as_object)->SmiPrint();
+      Smi::cast(this_as_object)->SmiPrint(out);
     } else {
-      HeapObject::cast(this_as_object)->HeapObjectPrint();
+      HeapObject::cast(this_as_object)->HeapObjectPrint(out);
     }
   } else {
-    Failure::cast(this)->FailurePrint();
+    Failure::cast(this)->FailurePrint(out);
   }
-  Flush();
+  Flush(out);
 }
 
 
-void MaybeObject::PrintLn() {
-  Print();
-  PrintF("\n");
+void MaybeObject::PrintLn(FILE* out) {
+  Print(out);
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void MaybeObject::Verify() {
   Object* this_as_object;
   if (ToObject(&this_as_object)) {
@@ -92,114 +94,120 @@ void Smi::SmiVerify() {
 void Failure::FailureVerify() {
   ASSERT(IsFailure());
 }
+#endif  // DEBUG
 
 
-void HeapObject::PrintHeader(const char* id) {
-  PrintF("%p: [%s]\n", reinterpret_cast<void*>(this), id);
+#ifdef OBJECT_PRINT
+void HeapObject::PrintHeader(FILE* out, const char* id) {
+  PrintF(out, "%p: [%s]\n", reinterpret_cast<void*>(this), id);
 }
 
 
-void HeapObject::HeapObjectPrint() {
+void HeapObject::HeapObjectPrint(FILE* out) {
   InstanceType instance_type = map()->instance_type();
 
   HandleScope scope;
   if (instance_type < FIRST_NONSTRING_TYPE) {
-    String::cast(this)->StringPrint();
+    String::cast(this)->StringPrint(out);
     return;
   }
 
   switch (instance_type) {
     case MAP_TYPE:
-      Map::cast(this)->MapPrint();
+      Map::cast(this)->MapPrint(out);
       break;
     case HEAP_NUMBER_TYPE:
-      HeapNumber::cast(this)->HeapNumberPrint();
+      HeapNumber::cast(this)->HeapNumberPrint(out);
       break;
     case FIXED_ARRAY_TYPE:
-      FixedArray::cast(this)->FixedArrayPrint();
+      FixedArray::cast(this)->FixedArrayPrint(out);
       break;
     case BYTE_ARRAY_TYPE:
-      ByteArray::cast(this)->ByteArrayPrint();
+      ByteArray::cast(this)->ByteArrayPrint(out);
       break;
     case PIXEL_ARRAY_TYPE:
-      PixelArray::cast(this)->PixelArrayPrint();
+      PixelArray::cast(this)->PixelArrayPrint(out);
       break;
     case EXTERNAL_BYTE_ARRAY_TYPE:
-      ExternalByteArray::cast(this)->ExternalByteArrayPrint();
+      ExternalByteArray::cast(this)->ExternalByteArrayPrint(out);
       break;
     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
-      ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayPrint();
+      ExternalUnsignedByteArray::cast(this)
+          ->ExternalUnsignedByteArrayPrint(out);
       break;
     case EXTERNAL_SHORT_ARRAY_TYPE:
-      ExternalShortArray::cast(this)->ExternalShortArrayPrint();
+      ExternalShortArray::cast(this)->ExternalShortArrayPrint(out);
       break;
     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
-      ExternalUnsignedShortArray::cast(this)->ExternalUnsignedShortArrayPrint();
+      ExternalUnsignedShortArray::cast(this)
+          ->ExternalUnsignedShortArrayPrint(out);
       break;
     case EXTERNAL_INT_ARRAY_TYPE:
-      ExternalIntArray::cast(this)->ExternalIntArrayPrint();
+      ExternalIntArray::cast(this)->ExternalIntArrayPrint(out);
       break;
     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
-      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint();
+      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint(out);
       break;
     case EXTERNAL_FLOAT_ARRAY_TYPE:
-      ExternalFloatArray::cast(this)->ExternalFloatArrayPrint();
+      ExternalFloatArray::cast(this)->ExternalFloatArrayPrint(out);
       break;
     case FILLER_TYPE:
-      PrintF("filler");
+      PrintF(out, "filler");
       break;
     case JS_OBJECT_TYPE:  // fall through
     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
     case JS_ARRAY_TYPE:
     case JS_REGEXP_TYPE:
-      JSObject::cast(this)->JSObjectPrint();
+      JSObject::cast(this)->JSObjectPrint(out);
       break;
     case ODDBALL_TYPE:
-      Oddball::cast(this)->to_string()->Print();
+      Oddball::cast(this)->to_string()->Print(out);
       break;
     case JS_FUNCTION_TYPE:
-      JSFunction::cast(this)->JSFunctionPrint();
+      JSFunction::cast(this)->JSFunctionPrint(out);
       break;
     case JS_GLOBAL_PROXY_TYPE:
-      JSGlobalProxy::cast(this)->JSGlobalProxyPrint();
+      JSGlobalProxy::cast(this)->JSGlobalProxyPrint(out);
       break;
     case JS_GLOBAL_OBJECT_TYPE:
-      JSGlobalObject::cast(this)->JSGlobalObjectPrint();
+      JSGlobalObject::cast(this)->JSGlobalObjectPrint(out);
       break;
     case JS_BUILTINS_OBJECT_TYPE:
-      JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint();
+      JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(out);
       break;
     case JS_VALUE_TYPE:
-      PrintF("Value wrapper around:");
-      JSValue::cast(this)->value()->Print();
+      PrintF(out, "Value wrapper around:");
+      JSValue::cast(this)->value()->Print(out);
       break;
     case CODE_TYPE:
-      Code::cast(this)->CodePrint();
+      Code::cast(this)->CodePrint(out);
       break;
     case PROXY_TYPE:
-      Proxy::cast(this)->ProxyPrint();
+      Proxy::cast(this)->ProxyPrint(out);
       break;
     case SHARED_FUNCTION_INFO_TYPE:
-      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint();
+      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
       break;
     case JS_GLOBAL_PROPERTY_CELL_TYPE:
-      JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint();
+      JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint(out);
       break;
 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   case NAME##_TYPE:                        \
-    Name::cast(this)->Name##Print();       \
+    Name::cast(this)->Name##Print(out);    \
     break;
   STRUCT_LIST(MAKE_STRUCT_CASE)
 #undef MAKE_STRUCT_CASE
 
     default:
-      PrintF("UNKNOWN TYPE %d", map()->instance_type());
+      PrintF(out, "UNKNOWN TYPE %d", map()->instance_type());
       UNREACHABLE();
       break;
   }
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void HeapObject::HeapObjectVerify() {
   InstanceType instance_type = map()->instance_type();
 
@@ -312,53 +320,57 @@ void HeapObject::VerifyHeapPointer(Object* p) {
 void HeapNumber::HeapNumberVerify() {
   ASSERT(IsHeapNumber());
 }
+#endif  // DEBUG
 
 
-void ByteArray::ByteArrayPrint() {
-  PrintF("byte array, data starts at %p", GetDataStartAddress());
+#ifdef OBJECT_PRINT
+void ByteArray::ByteArrayPrint(FILE* out) {
+  PrintF(out, "byte array, data starts at %p", GetDataStartAddress());
 }
 
 
-void PixelArray::PixelArrayPrint() {
-  PrintF("pixel array");
+void PixelArray::PixelArrayPrint(FILE* out) {
+  PrintF(out, "pixel array");
 }
 
 
-void ExternalByteArray::ExternalByteArrayPrint() {
-  PrintF("external byte array");
+void ExternalByteArray::ExternalByteArrayPrint(FILE* out) {
+  PrintF(out, "external byte array");
 }
 
 
-void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint() {
-  PrintF("external unsigned byte array");
+void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint(FILE* out) {
+  PrintF(out, "external unsigned byte array");
 }
 
 
-void ExternalShortArray::ExternalShortArrayPrint() {
-  PrintF("external short array");
+void ExternalShortArray::ExternalShortArrayPrint(FILE* out) {
+  PrintF(out, "external short array");
 }
 
 
-void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint() {
-  PrintF("external unsigned short array");
+void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint(FILE* out) {
+  PrintF(out, "external unsigned short array");
 }
 
 
-void ExternalIntArray::ExternalIntArrayPrint() {
-  PrintF("external int array");
+void ExternalIntArray::ExternalIntArrayPrint(FILE* out) {
+  PrintF(out, "external int array");
 }
 
 
-void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint() {
-  PrintF("external unsigned int array");
+void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint(FILE* out) {
+  PrintF(out, "external unsigned int array");
 }
 
 
-void ExternalFloatArray::ExternalFloatArrayPrint() {
-  PrintF("external float array");
+void ExternalFloatArray::ExternalFloatArrayPrint(FILE* out) {
+  PrintF(out, "external float array");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void ByteArray::ByteArrayVerify() {
   ASSERT(IsByteArray());
 }
@@ -402,38 +414,40 @@ void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() {
 void ExternalFloatArray::ExternalFloatArrayVerify() {
   ASSERT(IsExternalFloatArray());
 }
+#endif  // DEBUG
 
 
-void JSObject::PrintProperties() {
+#ifdef OBJECT_PRINT
+void JSObject::PrintProperties(FILE* out) {
   if (HasFastProperties()) {
     DescriptorArray* descs = map()->instance_descriptors();
     for (int i = 0; i < descs->number_of_descriptors(); i++) {
-      PrintF("   ");
-      descs->GetKey(i)->StringPrint();
-      PrintF(": ");
+      PrintF(out, "   ");
+      descs->GetKey(i)->StringPrint(out);
+      PrintF(out, ": ");
       switch (descs->GetType(i)) {
         case FIELD: {
           int index = descs->GetFieldIndex(i);
-          FastPropertyAt(index)->ShortPrint();
-          PrintF(" (field at offset %d)\n", index);
+          FastPropertyAt(index)->ShortPrint(out);
+          PrintF(out, " (field at offset %d)\n", index);
           break;
         }
         case CONSTANT_FUNCTION:
-          descs->GetConstantFunction(i)->ShortPrint();
-          PrintF(" (constant function)\n");
+          descs->GetConstantFunction(i)->ShortPrint(out);
+          PrintF(out, " (constant function)\n");
           break;
         case CALLBACKS:
-          descs->GetCallbacksObject(i)->ShortPrint();
-          PrintF(" (callback)\n");
+          descs->GetCallbacksObject(i)->ShortPrint(out);
+          PrintF(out, " (callback)\n");
           break;
         case MAP_TRANSITION:
-          PrintF(" (map transition)\n");
+          PrintF(out, " (map transition)\n");
           break;
         case CONSTANT_TRANSITION:
-          PrintF(" (constant transition)\n");
+          PrintF(out, " (constant transition)\n");
           break;
         case NULL_DESCRIPTOR:
-          PrintF(" (null descriptor)\n");
+          PrintF(out, " (null descriptor)\n");
           break;
         default:
           UNREACHABLE();
@@ -441,34 +455,34 @@ void JSObject::PrintProperties() {
       }
     }
   } else {
-    property_dictionary()->Print();
+    property_dictionary()->Print(out);
   }
 }
 
 
-void JSObject::PrintElements() {
+void JSObject::PrintElements(FILE* out) {
   switch (GetElementsKind()) {
     case FAST_ELEMENTS: {
       // Print in array notation for non-sparse arrays.
       FixedArray* p = FixedArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: ", i);
-        p->get(i)->ShortPrint();
-        PrintF("\n");
+        PrintF(out, "   %d: ", i);
+        p->get(i)->ShortPrint(out);
+        PrintF(out, "\n");
       }
       break;
     }
     case PIXEL_ELEMENTS: {
       PixelArray* p = PixelArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, p->get(i));
+        PrintF(out, "   %d: %d\n", i, p->get(i));
       }
       break;
     }
     case EXTERNAL_BYTE_ELEMENTS: {
       ExternalByteArray* p = ExternalByteArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
       }
       break;
     }
@@ -476,14 +490,14 @@ void JSObject::PrintElements() {
       ExternalUnsignedByteArray* p =
           ExternalUnsignedByteArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
       }
       break;
     }
     case EXTERNAL_SHORT_ELEMENTS: {
       ExternalShortArray* p = ExternalShortArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
       }
       break;
     }
@@ -491,14 +505,14 @@ void JSObject::PrintElements() {
       ExternalUnsignedShortArray* p =
           ExternalUnsignedShortArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
       }
       break;
     }
     case EXTERNAL_INT_ELEMENTS: {
       ExternalIntArray* p = ExternalIntArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
       }
       break;
     }
@@ -506,19 +520,19 @@ void JSObject::PrintElements() {
       ExternalUnsignedIntArray* p =
           ExternalUnsignedIntArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
+        PrintF(out, "   %d: %d\n", i, static_cast<int>(p->get(i)));
       }
       break;
     }
     case EXTERNAL_FLOAT_ELEMENTS: {
       ExternalFloatArray* p = ExternalFloatArray::cast(elements());
       for (int i = 0; i < p->length(); i++) {
-        PrintF("   %d: %f\n", i, p->get(i));
+        PrintF(out, "   %d: %f\n", i, p->get(i));
       }
       break;
     }
     case DICTIONARY_ELEMENTS:
-      elements()->Print();
+      elements()->Print(out);
       break;
     default:
       UNREACHABLE();
@@ -527,17 +541,19 @@ void JSObject::PrintElements() {
 }
 
 
-void JSObject::JSObjectPrint() {
-  PrintF("%p: [JSObject]\n", reinterpret_cast<void*>(this));
-  PrintF(" - map = %p\n", reinterpret_cast<void*>(map()));
-  PrintF(" - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
-  PrintF(" {\n");
-  PrintProperties();
-  PrintElements();
-  PrintF(" }\n");
+void JSObject::JSObjectPrint(FILE* out) {
+  PrintF(out, "%p: [JSObject]\n", reinterpret_cast<void*>(this));
+  PrintF(out, " - map = %p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - prototype = %p\n", reinterpret_cast<void*>(GetPrototype()));
+  PrintF(out, " {\n");
+  PrintProperties(out);
+  PrintElements(out);
+  PrintF(out, " }\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void JSObject::JSObjectVerify() {
   VerifyHeapPointer(properties());
   VerifyHeapPointer(elements());
@@ -551,8 +567,10 @@ void JSObject::JSObjectVerify() {
           elements()->map() == Heap::fixed_cow_array_map()));
   ASSERT(map()->has_fast_elements() == HasFastElements());
 }
+#endif  // DEBUG
 
 
+#ifdef OBJECT_PRINT
 static const char* TypeToString(InstanceType type) {
   switch (type) {
     case INVALID_TYPE: return "INVALID";
@@ -608,42 +626,44 @@ static const char* TypeToString(InstanceType type) {
 }
 
 
-void Map::MapPrint() {
-  HeapObject::PrintHeader("Map");
-  PrintF(" - type: %s\n", TypeToString(instance_type()));
-  PrintF(" - instance size: %d\n", instance_size());
-  PrintF(" - inobject properties: %d\n", inobject_properties());
-  PrintF(" - pre-allocated property fields: %d\n",
+void Map::MapPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Map");
+  PrintF(out, " - type: %s\n", TypeToString(instance_type()));
+  PrintF(out, " - instance size: %d\n", instance_size());
+  PrintF(out, " - inobject properties: %d\n", inobject_properties());
+  PrintF(out, " - pre-allocated property fields: %d\n",
       pre_allocated_property_fields());
-  PrintF(" - unused property fields: %d\n", unused_property_fields());
+  PrintF(out, " - unused property fields: %d\n", unused_property_fields());
   if (is_hidden_prototype()) {
-    PrintF(" - hidden_prototype\n");
+    PrintF(out, " - hidden_prototype\n");
   }
   if (has_named_interceptor()) {
-    PrintF(" - named_interceptor\n");
+    PrintF(out, " - named_interceptor\n");
   }
   if (has_indexed_interceptor()) {
-    PrintF(" - indexed_interceptor\n");
+    PrintF(out, " - indexed_interceptor\n");
   }
   if (is_undetectable()) {
-    PrintF(" - undetectable\n");
+    PrintF(out, " - undetectable\n");
   }
   if (has_instance_call_handler()) {
-    PrintF(" - instance_call_handler\n");
+    PrintF(out, " - instance_call_handler\n");
   }
   if (is_access_check_needed()) {
-    PrintF(" - access_check_needed\n");
+    PrintF(out, " - access_check_needed\n");
   }
-  PrintF(" - instance descriptors: ");
-  instance_descriptors()->ShortPrint();
-  PrintF("\n - prototype: ");
-  prototype()->ShortPrint();
-  PrintF("\n - constructor: ");
-  constructor()->ShortPrint();
-  PrintF("\n");
+  PrintF(out, " - instance descriptors: ");
+  instance_descriptors()->ShortPrint(out);
+  PrintF(out, "\n - prototype: ");
+  prototype()->ShortPrint(out);
+  PrintF(out, "\n - constructor: ");
+  constructor()->ShortPrint(out);
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void Map::MapVerify() {
   ASSERT(!Heap::InNewSpace(this));
   ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
@@ -665,17 +685,21 @@ void Map::SharedMapVerify() {
   ASSERT_EQ(StaticVisitorBase::GetVisitorId(instance_type(), instance_size()),
       visitor_id());
 }
+#endif  // DEBUG
 
 
-void CodeCache::CodeCachePrint() {
-  HeapObject::PrintHeader("CodeCache");
-  PrintF("\n - default_cache: ");
-  default_cache()->ShortPrint();
-  PrintF("\n - normal_type_cache: ");
-  normal_type_cache()->ShortPrint();
+#ifdef OBJECT_PRINT
+void CodeCache::CodeCachePrint(FILE* out) {
+  HeapObject::PrintHeader(out, "CodeCache");
+  PrintF(out, "\n - default_cache: ");
+  default_cache()->ShortPrint(out);
+  PrintF(out, "\n - normal_type_cache: ");
+  normal_type_cache()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void CodeCache::CodeCacheVerify() {
   VerifyHeapPointer(default_cache());
   VerifyHeapPointer(normal_type_cache());
@@ -683,19 +707,23 @@ void CodeCache::CodeCacheVerify() {
   ASSERT(normal_type_cache()->IsUndefined()
          || normal_type_cache()->IsCodeCacheHashTable());
 }
+#endif  // DEBUG
 
 
-void FixedArray::FixedArrayPrint() {
-  HeapObject::PrintHeader("FixedArray");
-  PrintF(" - length: %d", length());
+#ifdef OBJECT_PRINT
+void FixedArray::FixedArrayPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "FixedArray");
+  PrintF(out, " - length: %d", length());
   for (int i = 0; i < length(); i++) {
-    PrintF("\n  [%d]: ", i);
-    get(i)->ShortPrint();
+    PrintF(out, "\n  [%d]: ", i);
+    get(i)->ShortPrint(out);
   }
-  PrintF("\n");
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void FixedArray::FixedArrayVerify() {
   for (int i = 0; i < length(); i++) {
     Object* e = get(i);
@@ -706,39 +734,57 @@ void FixedArray::FixedArrayVerify() {
     }
   }
 }
+#endif  // DEBUG
 
 
-void JSValue::JSValuePrint() {
-  HeapObject::PrintHeader("ValueObject");
-  value()->Print();
+#ifdef OBJECT_PRINT
+void JSValue::JSValuePrint(FILE* out) {
+  HeapObject::PrintHeader(out, "ValueObject");
+  value()->Print(out);
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void JSValue::JSValueVerify() {
   Object* v = value();
   if (v->IsHeapObject()) {
     VerifyHeapPointer(v);
   }
 }
+#endif  // DEBUG
 
 
-void String::StringPrint() {
+#ifdef OBJECT_PRINT
+void String::StringPrint(FILE* out) {
   if (StringShape(this).IsSymbol()) {
-    PrintF("#");
+    PrintF(out, "#");
   } else if (StringShape(this).IsCons()) {
-    PrintF("c\"");
+    PrintF(out, "c\"");
   } else {
-    PrintF("\"");
+    PrintF(out, "\"");
   }
 
-  for (int i = 0; i < length(); i++) {
-    PrintF("%c", Get(i));
+  const char truncated_epilogue[] = "...<truncated>";
+  int len = length();
+  if (!FLAG_use_verbose_printer) {
+    if (len > 100) {
+      len = 100 - sizeof(truncated_epilogue);
+    }
+  }
+  for (int i = 0; i < len; i++) {
+    PrintF(out, "%c", Get(i));
+  }
+  if (len != length()) {
+    PrintF(out, "%s", truncated_epilogue);
   }
 
-  if (!StringShape(this).IsSymbol()) PrintF("\"");
+  if (!StringShape(this).IsSymbol()) PrintF(out, "\"");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void String::StringVerify() {
   CHECK(IsString());
   CHECK(length() >= 0 && length() <= Smi::kMaxValue);
@@ -746,32 +792,36 @@ void String::StringVerify() {
     CHECK(!Heap::InNewSpace(this));
   }
 }
+#endif  // DEBUG
 
 
-void JSFunction::JSFunctionPrint() {
-  HeapObject::PrintHeader("Function");
-  PrintF(" - map = 0x%p\n", reinterpret_cast<void*>(map()));
-  PrintF(" - initial_map = ");
+#ifdef OBJECT_PRINT
+void JSFunction::JSFunctionPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Function");
+  PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
+  PrintF(out, " - initial_map = ");
   if (has_initial_map()) {
-    initial_map()->ShortPrint();
+    initial_map()->ShortPrint(out);
   }
-  PrintF("\n - shared_info = ");
-  shared()->ShortPrint();
-  PrintF("\n   - name = ");
-  shared()->name()->Print();
-  PrintF("\n - context = ");
-  unchecked_context()->ShortPrint();
-  PrintF("\n - code = ");
-  code()->ShortPrint();
-  PrintF("\n");
+  PrintF(out, "\n - shared_info = ");
+  shared()->ShortPrint(out);
+  PrintF(out, "\n   - name = ");
+  shared()->name()->Print(out);
+  PrintF(out, "\n - context = ");
+  unchecked_context()->ShortPrint(out);
+  PrintF(out, "\n - code = ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n");
 
-  PrintProperties();
-  PrintElements();
+  PrintProperties(out);
+  PrintElements(out);
 
-  PrintF("\n");
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void JSFunction::JSFunctionVerify() {
   CHECK(IsJSFunction());
   VerifyObjectField(kPrototypeOrInitialMapOffset);
@@ -779,36 +829,41 @@ void JSFunction::JSFunctionVerify() {
   CHECK(next_function_link()->IsUndefined() ||
         next_function_link()->IsJSFunction());
 }
+#endif  // DEBUG
 
 
-void SharedFunctionInfo::SharedFunctionInfoPrint() {
-  HeapObject::PrintHeader("SharedFunctionInfo");
-  PrintF(" - name: ");
-  name()->ShortPrint();
-  PrintF("\n - expected_nof_properties: %d", expected_nof_properties());
-  PrintF("\n - instance class name = ");
-  instance_class_name()->Print();
-  PrintF("\n - code = ");
-  code()->ShortPrint();
-  PrintF("\n - source code = ");
-  GetSourceCode()->ShortPrint();
+#ifdef OBJECT_PRINT
+void SharedFunctionInfo::SharedFunctionInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "SharedFunctionInfo");
+  PrintF(out, " - name: ");
+  name()->ShortPrint(out);
+  PrintF(out, "\n - expected_nof_properties: %d", expected_nof_properties());
+  PrintF(out, "\n - instance class name = ");
+  instance_class_name()->Print(out);
+  PrintF(out, "\n - code = ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n - source code = ");
+  GetSourceCode()->ShortPrint(out);
   // Script files are often large, hard to read.
-  // PrintF("\n - script =");
-  // script()->Print();
-  PrintF("\n - function token position = %d", function_token_position());
-  PrintF("\n - start position = %d", start_position());
-  PrintF("\n - end position = %d", end_position());
-  PrintF("\n - is expression = %d", is_expression());
-  PrintF("\n - debug info = ");
-  debug_info()->ShortPrint();
-  PrintF("\n - length = %d", length());
-  PrintF("\n - has_only_simple_this_property_assignments = %d",
+  // PrintF(out, "\n - script =");
+  // script()->Print(out);
+  PrintF(out, "\n - function token position = %d", function_token_position());
+  PrintF(out, "\n - start position = %d", start_position());
+  PrintF(out, "\n - end position = %d", end_position());
+  PrintF(out, "\n - is expression = %d", is_expression());
+  PrintF(out, "\n - debug info = ");
+  debug_info()->ShortPrint(out);
+  PrintF(out, "\n - length = %d", length());
+  PrintF(out, "\n - has_only_simple_this_property_assignments = %d",
          has_only_simple_this_property_assignments());
-  PrintF("\n - this_property_assignments = ");
-  this_property_assignments()->ShortPrint();
-  PrintF("\n");
+  PrintF(out, "\n - this_property_assignments = ");
+  this_property_assignments()->ShortPrint(out);
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
+
 
+#ifdef DEBUG
 void SharedFunctionInfo::SharedFunctionInfoVerify() {
   CHECK(IsSharedFunctionInfo());
   VerifyObjectField(kNameOffset);
@@ -819,17 +874,21 @@ void SharedFunctionInfo::SharedFunctionInfoVerify() {
   VerifyObjectField(kScriptOffset);
   VerifyObjectField(kDebugInfoOffset);
 }
+#endif  // DEBUG
 
 
-void JSGlobalProxy::JSGlobalProxyPrint() {
-  PrintF("global_proxy");
-  JSObjectPrint();
-  PrintF("context : ");
-  context()->ShortPrint();
-  PrintF("\n");
+#ifdef OBJECT_PRINT
+void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
+  PrintF(out, "global_proxy");
+  JSObjectPrint(out);
+  PrintF(out, "context : ");
+  context()->ShortPrint(out);
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void JSGlobalProxy::JSGlobalProxyVerify() {
   CHECK(IsJSGlobalProxy());
   JSObjectVerify();
@@ -839,17 +898,21 @@ void JSGlobalProxy::JSGlobalProxyVerify() {
   CHECK(HasFastElements());
   CHECK_EQ(0, FixedArray::cast(elements())->length());
 }
+#endif  // DEBUG
 
 
-void JSGlobalObject::JSGlobalObjectPrint() {
-  PrintF("global ");
-  JSObjectPrint();
-  PrintF("global context : ");
-  global_context()->ShortPrint();
-  PrintF("\n");
+#ifdef OBJECT_PRINT
+void JSGlobalObject::JSGlobalObjectPrint(FILE* out) {
+  PrintF(out, "global ");
+  JSObjectPrint(out);
+  PrintF(out, "global context : ");
+  global_context()->ShortPrint(out);
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void JSGlobalObject::JSGlobalObjectVerify() {
   CHECK(IsJSGlobalObject());
   JSObjectVerify();
@@ -859,14 +922,18 @@ void JSGlobalObject::JSGlobalObjectVerify() {
     VerifyObjectField(i);
   }
 }
+#endif  // DEBUG
 
 
-void JSBuiltinsObject::JSBuiltinsObjectPrint() {
-  PrintF("builtins ");
-  JSObjectPrint();
+#ifdef OBJECT_PRINT
+void JSBuiltinsObject::JSBuiltinsObjectPrint(FILE* out) {
+  PrintF(out, "builtins ");
+  JSObjectPrint(out);
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void JSBuiltinsObject::JSBuiltinsObjectVerify() {
   CHECK(IsJSBuiltinsObject());
   JSObjectVerify();
@@ -897,21 +964,27 @@ void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
   CHECK(IsJSGlobalPropertyCell());
   VerifyObjectField(kValueOffset);
 }
+#endif  // DEBUG
 
 
-void JSGlobalPropertyCell::JSGlobalPropertyCellPrint() {
-  HeapObject::PrintHeader("JSGlobalPropertyCell");
+#ifdef OBJECT_PRINT
+void JSGlobalPropertyCell::JSGlobalPropertyCellPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "JSGlobalPropertyCell");
 }
 
 
-void Code::CodePrint() {
-  HeapObject::PrintHeader("Code");
+void Code::CodePrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Code");
 #ifdef ENABLE_DISASSEMBLER
-  Disassemble(NULL);
+  if (FLAG_use_verbose_printer) {
+    Disassemble(NULL, out);
+  }
 #endif
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void Code::CodeVerify() {
   CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
                   kCodeAlignment));
@@ -966,13 +1039,17 @@ void JSRegExp::JSRegExpVerify() {
       break;
   }
 }
+#endif  // DEBUG
 
 
-void Proxy::ProxyPrint() {
-  PrintF("proxy to %p", proxy());
+#ifdef OBJECT_PRINT
+void Proxy::ProxyPrint(FILE* out) {
+  PrintF(out, "proxy to %p", proxy());
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void Proxy::ProxyVerify() {
   ASSERT(IsProxy());
 }
@@ -986,38 +1063,50 @@ void AccessorInfo::AccessorInfoVerify() {
   VerifyPointer(data());
   VerifyPointer(flag());
 }
+#endif  // DEBUG
+
 
-void AccessorInfo::AccessorInfoPrint() {
-  HeapObject::PrintHeader("AccessorInfo");
-  PrintF("\n - getter: ");
-  getter()->ShortPrint();
-  PrintF("\n - setter: ");
-  setter()->ShortPrint();
-  PrintF("\n - name: ");
-  name()->ShortPrint();
-  PrintF("\n - data: ");
-  data()->ShortPrint();
-  PrintF("\n - flag: ");
-  flag()->ShortPrint();
+#ifdef OBJECT_PRINT
+void AccessorInfo::AccessorInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "AccessorInfo");
+  PrintF(out, "\n - getter: ");
+  getter()->ShortPrint(out);
+  PrintF(out, "\n - setter: ");
+  setter()->ShortPrint(out);
+  PrintF(out, "\n - name: ");
+  name()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+  PrintF(out, "\n - flag: ");
+  flag()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
 
+
+#ifdef DEBUG
 void AccessCheckInfo::AccessCheckInfoVerify() {
   CHECK(IsAccessCheckInfo());
   VerifyPointer(named_callback());
   VerifyPointer(indexed_callback());
   VerifyPointer(data());
 }
+#endif  // DEBUG
 
-void AccessCheckInfo::AccessCheckInfoPrint() {
-  HeapObject::PrintHeader("AccessCheckInfo");
-  PrintF("\n - named_callback: ");
-  named_callback()->ShortPrint();
-  PrintF("\n - indexed_callback: ");
-  indexed_callback()->ShortPrint();
-  PrintF("\n - data: ");
-  data()->ShortPrint();
+
+#ifdef OBJECT_PRINT
+void AccessCheckInfo::AccessCheckInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "AccessCheckInfo");
+  PrintF(out, "\n - named_callback: ");
+  named_callback()->ShortPrint(out);
+  PrintF(out, "\n - indexed_callback: ");
+  indexed_callback()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
+
 
+#ifdef DEBUG
 void InterceptorInfo::InterceptorInfoVerify() {
   CHECK(IsInterceptorInfo());
   VerifyPointer(getter());
@@ -1027,38 +1116,50 @@ void InterceptorInfo::InterceptorInfoVerify() {
   VerifyPointer(enumerator());
   VerifyPointer(data());
 }
+#endif  // DEBUG
+
 
-void InterceptorInfo::InterceptorInfoPrint() {
-  HeapObject::PrintHeader("InterceptorInfo");
-  PrintF("\n - getter: ");
-  getter()->ShortPrint();
-  PrintF("\n - setter: ");
-  setter()->ShortPrint();
-  PrintF("\n - query: ");
-  query()->ShortPrint();
-  PrintF("\n - deleter: ");
-  deleter()->ShortPrint();
-  PrintF("\n - enumerator: ");
-  enumerator()->ShortPrint();
-  PrintF("\n - data: ");
-  data()->ShortPrint();
+#ifdef OBJECT_PRINT
+void InterceptorInfo::InterceptorInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "InterceptorInfo");
+  PrintF(out, "\n - getter: ");
+  getter()->ShortPrint(out);
+  PrintF(out, "\n - setter: ");
+  setter()->ShortPrint(out);
+  PrintF(out, "\n - query: ");
+  query()->ShortPrint(out);
+  PrintF(out, "\n - deleter: ");
+  deleter()->ShortPrint(out);
+  PrintF(out, "\n - enumerator: ");
+  enumerator()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
+
 
+#ifdef DEBUG
 void CallHandlerInfo::CallHandlerInfoVerify() {
   CHECK(IsCallHandlerInfo());
   VerifyPointer(callback());
   VerifyPointer(data());
 }
+#endif  // DEBUG
+
 
-void CallHandlerInfo::CallHandlerInfoPrint() {
-  HeapObject::PrintHeader("CallHandlerInfo");
-  PrintF("\n - callback: ");
-  callback()->ShortPrint();
-  PrintF("\n - data: ");
-  data()->ShortPrint();
-  PrintF("\n - call_stub_cache: ");
+#ifdef OBJECT_PRINT
+void CallHandlerInfo::CallHandlerInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "CallHandlerInfo");
+  PrintF(out, "\n - callback: ");
+  callback()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+  PrintF(out, "\n - call_stub_cache: ");
 }
+#endif  // OBJECT_PRINT
 
+
+#ifdef DEBUG
 void TemplateInfo::TemplateInfoVerify() {
   VerifyPointer(tag());
   VerifyPointer(property_list());
@@ -1078,81 +1179,106 @@ void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
   VerifyPointer(signature());
   VerifyPointer(access_check_info());
 }
+#endif  // DEBUG
+
+
+#ifdef OBJECT_PRINT
+void FunctionTemplateInfo::FunctionTemplateInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "FunctionTemplateInfo");
+  PrintF(out, "\n - class name: ");
+  class_name()->ShortPrint(out);
+  PrintF(out, "\n - tag: ");
+  tag()->ShortPrint(out);
+  PrintF(out, "\n - property_list: ");
+  property_list()->ShortPrint(out);
+  PrintF(out, "\n - serial_number: ");
+  serial_number()->ShortPrint(out);
+  PrintF(out, "\n - call_code: ");
+  call_code()->ShortPrint(out);
+  PrintF(out, "\n - property_accessors: ");
+  property_accessors()->ShortPrint(out);
+  PrintF(out, "\n - prototype_template: ");
+  prototype_template()->ShortPrint(out);
+  PrintF(out, "\n - parent_template: ");
+  parent_template()->ShortPrint(out);
+  PrintF(out, "\n - named_property_handler: ");
+  named_property_handler()->ShortPrint(out);
+  PrintF(out, "\n - indexed_property_handler: ");
+  indexed_property_handler()->ShortPrint(out);
+  PrintF(out, "\n - instance_template: ");
+  instance_template()->ShortPrint(out);
+  PrintF(out, "\n - signature: ");
+  signature()->ShortPrint(out);
+  PrintF(out, "\n - access_check_info: ");
+  access_check_info()->ShortPrint(out);
+  PrintF(out, "\n - hidden_prototype: %s",
+         hidden_prototype() ? "true" : "false");
+  PrintF(out, "\n - undetectable: %s", undetectable() ? "true" : "false");
+  PrintF(out, "\n - need_access_check: %s",
+         needs_access_check() ? "true" : "false");
+}
+#endif  // OBJECT_PRINT
 
-void FunctionTemplateInfo::FunctionTemplateInfoPrint() {
-  HeapObject::PrintHeader("FunctionTemplateInfo");
-  PrintF("\n - class name: ");
-  class_name()->ShortPrint();
-  PrintF("\n - tag: ");
-  tag()->ShortPrint();
-  PrintF("\n - property_list: ");
-  property_list()->ShortPrint();
-  PrintF("\n - serial_number: ");
-  serial_number()->ShortPrint();
-  PrintF("\n - call_code: ");
-  call_code()->ShortPrint();
-  PrintF("\n - property_accessors: ");
-  property_accessors()->ShortPrint();
-  PrintF("\n - prototype_template: ");
-  prototype_template()->ShortPrint();
-  PrintF("\n - parent_template: ");
-  parent_template()->ShortPrint();
-  PrintF("\n - named_property_handler: ");
-  named_property_handler()->ShortPrint();
-  PrintF("\n - indexed_property_handler: ");
-  indexed_property_handler()->ShortPrint();
-  PrintF("\n - instance_template: ");
-  instance_template()->ShortPrint();
-  PrintF("\n - signature: ");
-  signature()->ShortPrint();
-  PrintF("\n - access_check_info: ");
-  access_check_info()->ShortPrint();
-  PrintF("\n - hidden_prototype: %s", hidden_prototype() ? "true" : "false");
-  PrintF("\n - undetectable: %s", undetectable() ? "true" : "false");
-  PrintF("\n - need_access_check: %s", needs_access_check() ? "true" : "false");
-}
 
+#ifdef DEBUG
 void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
   CHECK(IsObjectTemplateInfo());
   TemplateInfoVerify();
   VerifyPointer(constructor());
   VerifyPointer(internal_field_count());
 }
+#endif  // DEBUG
 
-void ObjectTemplateInfo::ObjectTemplateInfoPrint() {
-  HeapObject::PrintHeader("ObjectTemplateInfo");
-  PrintF("\n - constructor: ");
-  constructor()->ShortPrint();
-  PrintF("\n - internal_field_count: ");
-  internal_field_count()->ShortPrint();
+
+#ifdef OBJECT_PRINT
+void ObjectTemplateInfo::ObjectTemplateInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "ObjectTemplateInfo");
+  PrintF(out, "\n - constructor: ");
+  constructor()->ShortPrint(out);
+  PrintF(out, "\n - internal_field_count: ");
+  internal_field_count()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
+
 
+#ifdef DEBUG
 void SignatureInfo::SignatureInfoVerify() {
   CHECK(IsSignatureInfo());
   VerifyPointer(receiver());
   VerifyPointer(args());
 }
+#endif  // DEBUG
+
 
-void SignatureInfo::SignatureInfoPrint() {
-  HeapObject::PrintHeader("SignatureInfo");
-  PrintF("\n - receiver: ");
-  receiver()->ShortPrint();
-  PrintF("\n - args: ");
-  args()->ShortPrint();
+#ifdef OBJECT_PRINT
+void SignatureInfo::SignatureInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "SignatureInfo");
+  PrintF(out, "\n - receiver: ");
+  receiver()->ShortPrint(out);
+  PrintF(out, "\n - args: ");
+  args()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
+
 
+#ifdef DEBUG
 void TypeSwitchInfo::TypeSwitchInfoVerify() {
   CHECK(IsTypeSwitchInfo());
   VerifyPointer(types());
 }
+#endif  // DEBUG
+
 
-void TypeSwitchInfo::TypeSwitchInfoPrint() {
-  HeapObject::PrintHeader("TypeSwitchInfo");
-  PrintF("\n - types: ");
-  types()->ShortPrint();
+#ifdef OBJECT_PRINT
+void TypeSwitchInfo::TypeSwitchInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "TypeSwitchInfo");
+  PrintF(out, "\n - types: ");
+  types()->ShortPrint(out);
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void Script::ScriptVerify() {
   CHECK(IsScript());
   VerifyPointer(source());
@@ -1165,41 +1291,45 @@ void Script::ScriptVerify() {
   VerifyPointer(line_ends());
   VerifyPointer(id());
 }
+#endif  // DEBUG
 
 
-void Script::ScriptPrint() {
-  HeapObject::PrintHeader("Script");
-  PrintF("\n - source: ");
-  source()->ShortPrint();
-  PrintF("\n - name: ");
-  name()->ShortPrint();
-  PrintF("\n - line_offset: ");
-  line_offset()->ShortPrint();
-  PrintF("\n - column_offset: ");
-  column_offset()->ShortPrint();
-  PrintF("\n - type: ");
-  type()->ShortPrint();
-  PrintF("\n - id: ");
-  id()->ShortPrint();
-  PrintF("\n - data: ");
-  data()->ShortPrint();
-  PrintF("\n - context data: ");
-  context_data()->ShortPrint();
-  PrintF("\n - wrapper: ");
-  wrapper()->ShortPrint();
-  PrintF("\n - compilation type: ");
-  compilation_type()->ShortPrint();
-  PrintF("\n - line ends: ");
-  line_ends()->ShortPrint();
-  PrintF("\n - eval from shared: ");
-  eval_from_shared()->ShortPrint();
-  PrintF("\n - eval from instructions offset: ");
-  eval_from_instructions_offset()->ShortPrint();
-  PrintF("\n");
-}
+#ifdef OBJECT_PRINT
+void Script::ScriptPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "Script");
+  PrintF(out, "\n - source: ");
+  source()->ShortPrint(out);
+  PrintF(out, "\n - name: ");
+  name()->ShortPrint(out);
+  PrintF(out, "\n - line_offset: ");
+  line_offset()->ShortPrint(out);
+  PrintF(out, "\n - column_offset: ");
+  column_offset()->ShortPrint(out);
+  PrintF(out, "\n - type: ");
+  type()->ShortPrint(out);
+  PrintF(out, "\n - id: ");
+  id()->ShortPrint(out);
+  PrintF(out, "\n - data: ");
+  data()->ShortPrint(out);
+  PrintF(out, "\n - context data: ");
+  context_data()->ShortPrint(out);
+  PrintF(out, "\n - wrapper: ");
+  wrapper()->ShortPrint(out);
+  PrintF(out, "\n - compilation type: ");
+  compilation_type()->ShortPrint(out);
+  PrintF(out, "\n - line ends: ");
+  line_ends()->ShortPrint(out);
+  PrintF(out, "\n - eval from shared: ");
+  eval_from_shared()->ShortPrint(out);
+  PrintF(out, "\n - eval from instructions offset: ");
+  eval_from_instructions_offset()->ShortPrint(out);
+  PrintF(out, "\n");
+}
+#endif  // OBJECT_PRINT
 
 
 #ifdef ENABLE_DEBUGGER_SUPPORT
+#ifdef DEBUG
 void DebugInfo::DebugInfoVerify() {
   CHECK(IsDebugInfo());
   VerifyPointer(shared());
@@ -1207,21 +1337,25 @@ void DebugInfo::DebugInfoVerify() {
   VerifyPointer(code());
   VerifyPointer(break_points());
 }
+#endif  // DEBUG
 
 
-void DebugInfo::DebugInfoPrint() {
-  HeapObject::PrintHeader("DebugInfo");
-  PrintF("\n - shared: ");
-  shared()->ShortPrint();
-  PrintF("\n - original_code: ");
-  original_code()->ShortPrint();
-  PrintF("\n - code: ");
-  code()->ShortPrint();
-  PrintF("\n - break_points: ");
-  break_points()->Print();
+#ifdef OBJECT_PRINT
+void DebugInfo::DebugInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "DebugInfo");
+  PrintF(out, "\n - shared: ");
+  shared()->ShortPrint(out);
+  PrintF(out, "\n - original_code: ");
+  original_code()->ShortPrint(out);
+  PrintF(out, "\n - code: ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n - break_points: ");
+  break_points()->Print(out);
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 void BreakPointInfo::BreakPointInfoVerify() {
   CHECK(IsBreakPointInfo());
   code_position()->SmiVerify();
@@ -1229,19 +1363,23 @@ void BreakPointInfo::BreakPointInfoVerify() {
   statement_position()->SmiVerify();
   VerifyPointer(break_point_objects());
 }
+#endif  // DEBUG
 
 
-void BreakPointInfo::BreakPointInfoPrint() {
-  HeapObject::PrintHeader("BreakPointInfo");
-  PrintF("\n - code_position: %d", code_position()->value());
-  PrintF("\n - source_position: %d", source_position()->value());
-  PrintF("\n - statement_position: %d", statement_position()->value());
-  PrintF("\n - break_point_objects: ");
-  break_point_objects()->ShortPrint();
+#ifdef OBJECT_PRINT
+void BreakPointInfo::BreakPointInfoPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "BreakPointInfo");
+  PrintF(out, "\n - code_position: %d", code_position()->value());
+  PrintF(out, "\n - source_position: %d", source_position()->value());
+  PrintF(out, "\n - statement_position: %d", statement_position()->value());
+  PrintF(out, "\n - break_point_objects: ");
+  break_point_objects()->ShortPrint(out);
 }
-#endif
+#endif  // OBJECT_PRINT
+#endif  // ENABLE_DEBUGGER_SUPPORT
 
 
+#ifdef DEBUG
 void JSObject::IncrementSpillStatistics(SpillInformation* info) {
   info->number_of_objects_++;
   // Named properties
@@ -1324,20 +1462,24 @@ void JSObject::SpillInformation::Print() {
 
   PrintF("\n");
 }
+#endif  // DEBUG
 
 
-void DescriptorArray::PrintDescriptors() {
-  PrintF("Descriptor array  %d\n", number_of_descriptors());
+#ifdef OBJECT_PRINT
+void DescriptorArray::PrintDescriptors(FILE* out) {
+  PrintF(out, "Descriptor array  %d\n", number_of_descriptors());
   for (int i = 0; i < number_of_descriptors(); i++) {
-    PrintF(" %d: ", i);
+    PrintF(out, " %d: ", i);
     Descriptor desc;
     Get(i, &desc);
-    desc.Print();
+    desc.Print(out);
   }
-  PrintF("\n");
+  PrintF(out, "\n");
 }
+#endif  // OBJECT_PRINT
 
 
+#ifdef DEBUG
 bool DescriptorArray::IsSortedNoDuplicates() {
   String* current_key = NULL;
   uint32_t current = 0;
index 96f5c4b..ab2f964 100644 (file)
@@ -553,11 +553,11 @@ Object* Object::GetPrototype() {
 }
 
 
-void Object::ShortPrint() {
+void Object::ShortPrint(FILE* out) {
   HeapStringAllocator allocator;
   StringStream accumulator(&allocator);
   ShortPrint(&accumulator);
-  accumulator.OutputToStdOut();
+  accumulator.OutputToFile(out);
 }
 
 
@@ -572,8 +572,8 @@ void Object::ShortPrint(StringStream* accumulator) {
 }
 
 
-void Smi::SmiPrint() {
-  PrintF("%d", value());
+void Smi::SmiPrint(FILE* out) {
+  PrintF(out, "%d", value());
 }
 
 
@@ -587,8 +587,8 @@ void Failure::FailurePrint(StringStream* accumulator) {
 }
 
 
-void Failure::FailurePrint() {
-  PrintF("Failure(%p)", reinterpret_cast<void*>(value()));
+void Failure::FailurePrint(FILE* out) {
+  PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
 }
 
 
@@ -1141,8 +1141,8 @@ Object* HeapNumber::HeapNumberToBoolean() {
 }
 
 
-void HeapNumber::HeapNumberPrint() {
-  PrintF("%.16g", Number());
+void HeapNumber::HeapNumberPrint(FILE* out) {
+  PrintF(out, "%.16g", Number());
 }
 
 
@@ -5467,9 +5467,9 @@ Object* JSFunction::SetInstanceClassName(String* name) {
 }
 
 
-void JSFunction::PrintName() {
+void JSFunction::PrintName(FILE* out) {
   SmartPointer<char> name = shared()->DebugName()->ToCString();
-  PrintF("%s", *name);
+  PrintF(out, "%s", *name);
 }
 
 
@@ -5999,18 +5999,18 @@ Map* Code::FindFirstMap() {
 
 #ifdef ENABLE_DISASSEMBLER
 
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
 
-void DeoptimizationInputData::DeoptimizationInputDataPrint() {
+void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
   disasm::NameConverter converter;
   int deopt_count = DeoptCount();
-  PrintF("Deoptimization Input Data (deopt points = %d)\n", deopt_count);
+  PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
   if (0 == deopt_count) return;
 
-  PrintF("%6s  %6s  %6s  %12s\n", "index", "ast id", "argc", "commands");
+  PrintF(out, "%6s  %6s  %6s  %12s\n", "index", "ast id", "argc", "commands");
   for (int i = 0; i < deopt_count; i++) {
     int command_count = 0;
-    PrintF("%6d  %6d  %6d",
+    PrintF(out, "%6d  %6d  %6d",
            i, AstId(i)->value(), ArgumentsStackHeight(i)->value());
     int translation_index = TranslationIndex(i)->value();
     TranslationIterator iterator(TranslationByteArray(), translation_index);
@@ -6019,7 +6019,8 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
     ASSERT(Translation::BEGIN == opcode);
     int frame_count = iterator.Next();
     if (FLAG_print_code_verbose) {
-      PrintF("  %s {count=%d}\n", Translation::StringFor(opcode), frame_count);
+      PrintF(out, "  %s {count=%d}\n", Translation::StringFor(opcode),
+             frame_count);
     }
 
     for (int i = 0; i < frame_count; ++i) {
@@ -6031,10 +6032,10 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           JSFunction::cast(LiteralArray()->get(function_id));
       unsigned height = iterator.Next();
       if (FLAG_print_code_verbose) {
-        PrintF("%24s  %s {ast_id=%d, function=",
+        PrintF(out, "%24s  %s {ast_id=%d, function=",
                "", Translation::StringFor(opcode), ast_id);
-        function->PrintName();
-        PrintF(", height=%u}\n", height);
+        function->PrintName(out);
+        PrintF(out, ", height=%u}\n", height);
       }
 
       // Size of translation is height plus all incoming arguments including
@@ -6044,13 +6045,13 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
       for (int j = 0; j < size; ++j) {
         opcode = static_cast<Translation::Opcode>(iterator.Next());
         if (FLAG_print_code_verbose) {
-          PrintF("%24s    %s ", "", Translation::StringFor(opcode));
+          PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
         }
 
         if (opcode == Translation::DUPLICATE) {
           opcode = static_cast<Translation::Opcode>(iterator.Next());
           if (FLAG_print_code_verbose) {
-            PrintF("%s ", Translation::StringFor(opcode));
+            PrintF(out, "%s ", Translation::StringFor(opcode));
           }
           --j;  // Two commands share the same frame index.
         }
@@ -6065,7 +6066,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::REGISTER: {
             int reg_code = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{input=%s}", converter.NameOfCPURegister(reg_code));
+              PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
             }
             break;
           }
@@ -6073,7 +6074,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::INT32_REGISTER: {
             int reg_code = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{input=%s}", converter.NameOfCPURegister(reg_code));
+              PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
             }
             break;
           }
@@ -6081,7 +6082,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::DOUBLE_REGISTER: {
             int reg_code = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{input=%s}",
+              PrintF(out, "{input=%s}",
                      DoubleRegister::AllocationIndexToString(reg_code));
             }
             break;
@@ -6090,7 +6091,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::STACK_SLOT: {
             int input_slot_index = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{input=%d}", input_slot_index);
+              PrintF(out, "{input=%d}", input_slot_index);
             }
             break;
           }
@@ -6098,7 +6099,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::INT32_STACK_SLOT: {
             int input_slot_index = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{input=%d}", input_slot_index);
+              PrintF(out, "{input=%d}", input_slot_index);
             }
             break;
           }
@@ -6106,7 +6107,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::DOUBLE_STACK_SLOT: {
             int input_slot_index = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{input=%d}", input_slot_index);
+              PrintF(out, "{input=%d}", input_slot_index);
             }
             break;
           }
@@ -6114,7 +6115,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::LITERAL: {
             unsigned literal_index = iterator.Next();
             if (FLAG_print_code_verbose)  {
-              PrintF("{literal_id=%u}", literal_index);
+              PrintF(out, "{literal_id=%u}", literal_index);
             }
             break;
           }
@@ -6122,16 +6123,16 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
           case Translation::ARGUMENTS_OBJECT:
             break;
         }
-        if (FLAG_print_code_verbose) PrintF("\n");
+        if (FLAG_print_code_verbose) PrintF(out, "\n");
       }
     }
-    if (!FLAG_print_code_verbose) PrintF("  %12d\n", command_count);
+    if (!FLAG_print_code_verbose) PrintF(out, "  %12d\n", command_count);
   }
 }
 
 
-void DeoptimizationOutputData::DeoptimizationOutputDataPrint() {
-  PrintF("Deoptimization Output Data (deopt points = %d)\n",
+void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
+  PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
          this->DeoptPoints());
   if (this->DeoptPoints() == 0) return;
 
@@ -6202,56 +6203,56 @@ const char* Code::PropertyType2String(PropertyType type) {
 }
 
 
-void Code::Disassemble(const char* name) {
-  PrintF("kind = %s\n", Kind2String(kind()));
+void Code::Disassemble(const char* name, FILE* out) {
+  PrintF(out, "kind = %s\n", Kind2String(kind()));
   if (is_inline_cache_stub()) {
-    PrintF("ic_state = %s\n", ICState2String(ic_state()));
-    PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
+    PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
+    PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
     if (ic_state() == MONOMORPHIC) {
-      PrintF("type = %s\n", PropertyType2String(type()));
+      PrintF(out, "type = %s\n", PropertyType2String(type()));
     }
   }
   if ((name != NULL) && (name[0] != '\0')) {
-    PrintF("name = %s\n", name);
+    PrintF(out, "name = %s\n", name);
   }
   if (kind() == OPTIMIZED_FUNCTION) {
-    PrintF("stack_slots = %d\n", stack_slots());
+    PrintF(out, "stack_slots = %d\n", stack_slots());
   }
 
-  PrintF("Instructions (size = %d)\n", instruction_size());
-  Disassembler::Decode(NULL, this);
-  PrintF("\n");
+  PrintF(out, "Instructions (size = %d)\n", instruction_size());
+  Disassembler::Decode(out, this);
+  PrintF(out, "\n");
 
 #ifdef DEBUG
   if (kind() == FUNCTION) {
     DeoptimizationOutputData* data =
         DeoptimizationOutputData::cast(this->deoptimization_data());
-    data->DeoptimizationOutputDataPrint();
+    data->DeoptimizationOutputDataPrint(out);
   } else if (kind() == OPTIMIZED_FUNCTION) {
     DeoptimizationInputData* data =
         DeoptimizationInputData::cast(this->deoptimization_data());
-    data->DeoptimizationInputDataPrint();
+    data->DeoptimizationInputDataPrint(out);
   }
   PrintF("\n");
 #endif
 
   if (kind() == OPTIMIZED_FUNCTION) {
     SafepointTable table(this);
-    PrintF("Safepoints (size = %u)\n", table.size());
+    PrintF(out, "Safepoints (size = %u)\n", table.size());
     for (unsigned i = 0; i < table.length(); i++) {
       unsigned pc_offset = table.GetPcOffset(i);
-      PrintF("%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
+      PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
       table.PrintEntry(i);
-      PrintF(" (sp -> fp)");
+      PrintF(out, " (sp -> fp)");
       int deoptimization_index = table.GetDeoptimizationIndex(i);
       if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
-        PrintF("  %6d", deoptimization_index);
+        PrintF(out, "  %6d", deoptimization_index);
       } else {
-        PrintF("  <none>");
+        PrintF(out, "  <none>");
       }
-      PrintF("\n");
+      PrintF(out, "\n");
     }
-    PrintF("\n");
+    PrintF(out, "\n");
   } else if (kind() == FUNCTION) {
     unsigned offset = stack_check_table_start();
     // If there is no stack check table, the "table start" will at or after
@@ -6260,19 +6261,19 @@ void Code::Disassemble(const char* name) {
       unsigned* address =
           reinterpret_cast<unsigned*>(instruction_start() + offset);
       unsigned length = address[0];
-      PrintF("Stack checks (size = %u)\n", length);
-      PrintF("ast_id  pc_offset\n");
+      PrintF(out, "Stack checks (size = %u)\n", length);
+      PrintF(out, "ast_id  pc_offset\n");
       for (unsigned i = 0; i < length; ++i) {
         unsigned index = (2 * i) + 1;
-        PrintF("%6u  %9u\n", address[index], address[index + 1]);
+        PrintF(out, "%6u  %9u\n", address[index], address[index + 1]);
       }
-      PrintF("\n");
+      PrintF(out, "\n");
     }
   }
 
   PrintF("RelocInfo (size = %d)\n", relocation_size());
-  for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print();
-  PrintF("\n");
+  for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
+  PrintF(out, "\n");
 }
 #endif  // ENABLE_DISASSEMBLER
 
@@ -7421,22 +7422,22 @@ bool JSObject::ShouldConvertToFastElements() {
 // class. This requires us to have the template functions put
 // together, so even though this function belongs in objects-debug.cc,
 // we keep it here instead to satisfy certain compilers.
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
 template<typename Shape, typename Key>
-void Dictionary<Shape, Key>::Print() {
+void Dictionary<Shape, Key>::Print(FILE* out) {
   int capacity = HashTable<Shape, Key>::Capacity();
   for (int i = 0; i < capacity; i++) {
     Object* k = HashTable<Shape, Key>::KeyAt(i);
     if (HashTable<Shape, Key>::IsKey(k)) {
-      PrintF(" ");
+      PrintF(out, " ");
       if (k->IsString()) {
-        String::cast(k)->StringPrint();
+        String::cast(k)->StringPrint(out);
       } else {
-        k->ShortPrint();
+        k->ShortPrint(out);
       }
-      PrintF(": ");
-      ValueAt(i)->ShortPrint();
-      PrintF("\n");
+      PrintF(out, ": ");
+      ValueAt(i)->ShortPrint(out);
+      PrintF(out, "\n");
     }
   }
 }
index 498ee45..c5fda7d 100644 (file)
@@ -607,10 +607,18 @@ class MaybeObject BASE_EMBEDDED {
     return reinterpret_cast<Object*>(this);
   }
 
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   // Prints this object with details.
-  void Print();
-  void PrintLn();
+  inline void Print() {
+    Print(stdout);
+  };
+  inline void PrintLn() {
+    PrintLn(stdout);
+  }
+  void Print(FILE* out);
+  void PrintLn(FILE* out);
+#endif
+#ifdef DEBUG
   // Verifies the object.
   void Verify();
 #endif
@@ -762,7 +770,10 @@ class Object : public MaybeObject {
 #endif
 
   // Prints this object without details.
-  void ShortPrint();
+  inline void ShortPrint() {
+    ShortPrint(stdout);
+  }
+  void ShortPrint(FILE* out);
 
   // Prints this object without details to a message accumulator.
   void ShortPrint(StringStream* accumulator);
@@ -801,7 +812,10 @@ class Smi: public Object {
   static inline Smi* cast(Object* object);
 
   // Dispatched behavior.
-  void SmiPrint();
+  inline void SmiPrint() {
+    SmiPrint(stdout);
+  }
+  void SmiPrint(FILE* out);
   void SmiPrint(StringStream* accumulator);
 #ifdef DEBUG
   void SmiVerify();
@@ -870,7 +884,10 @@ class Failure: public MaybeObject {
   static inline Failure* cast(MaybeObject* object);
 
   // Dispatched behavior.
-  void FailurePrint();
+  inline void FailurePrint() {
+    FailurePrint(stdout);
+  }
+  void FailurePrint(FILE* out);
   void FailurePrint(StringStream* accumulator);
 #ifdef DEBUG
   void FailureVerify();
@@ -1099,14 +1116,23 @@ class HeapObject: public Object {
 
   // Dispatched behavior.
   void HeapObjectShortPrint(StringStream* accumulator);
+#ifdef OBJECT_PRINT
+  inline void HeapObjectPrint() {
+    HeapObjectPrint(stdout);
+  }
+  void HeapObjectPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void HeapObjectPrint();
   void HeapObjectVerify();
   inline void VerifyObjectField(int offset);
   inline void VerifySmiField(int offset);
+#endif
 
-  void PrintHeader(const char* id);
+#ifdef OBJECT_PRINT
+  void PrintHeader(FILE* out, const char* id);
+#endif
 
+#ifdef DEBUG
   // Verify a pointer is a valid HeapObject pointer that points to object
   // areas in the heap.
   static void VerifyHeapPointer(Object* p);
@@ -1189,7 +1215,10 @@ class HeapNumber: public HeapObject {
 
   // Dispatched behavior.
   Object* HeapNumberToBoolean();
-  void HeapNumberPrint();
+  inline void HeapNumberPrint() {
+    HeapNumberPrint(stdout);
+  }
+  void HeapNumberPrint(FILE* out);
   void HeapNumberPrint(StringStream* accumulator);
 #ifdef DEBUG
   void HeapNumberVerify();
@@ -1649,12 +1678,28 @@ class JSObject: public HeapObject {
 
   // Dispatched behavior.
   void JSObjectShortPrint(StringStream* accumulator);
+#ifdef OBJECT_PRINT
+  inline void JSObjectPrint() {
+    JSObjectPrint(stdout);
+  }
+  void JSObjectPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSObjectPrint();
   void JSObjectVerify();
-  void PrintProperties();
-  void PrintElements();
+#endif
+#ifdef OBJECT_PRINT
+  inline void PrintProperties() {
+    PrintProperties(stdout);
+  }
+  void PrintProperties(FILE* out);
+
+  inline void PrintElements() {
+    PrintElements(stdout);
+  }
+  void PrintElements(FILE* out);
+#endif
 
+#ifdef DEBUG
   // Structure for collecting spill information about JSObjects.
   class SpillInformation {
    public:
@@ -1689,7 +1734,7 @@ class JSObject: public HeapObject {
   static const uint32_t kMaxGap = 1024;
   static const int kMaxFastElementsLength = 5000;
   static const int kInitialMaxFastElementArray = 100000;
-  static const int kMaxFastProperties = 8;
+  static const int kMaxFastProperties = 12;
   static const int kMaxInstanceSize = 255 * kPointerSize;
   // When extending the backing storage for property values, we increase
   // its size by more than the 1 entry necessary, so sequentially adding fields
@@ -1835,8 +1880,13 @@ class FixedArray: public HeapObject {
   static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void FixedArrayPrint() {
+    FixedArrayPrint(stdout);
+  }
+  void FixedArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void FixedArrayPrint();
   void FixedArrayVerify();
   // Checks if two FixedArrays have identical contents.
   bool IsEqualTo(FixedArray* other);
@@ -2012,10 +2062,15 @@ class DescriptorArray: public FixedArray {
   static const int kEnumCacheBridgeCacheOffset =
     kEnumCacheBridgeEnumOffset + kPointerSize;
 
-#ifdef DEBUG
+#ifdef OBJECT_PRINT
   // Print all the descriptors.
-  void PrintDescriptors();
+  inline void PrintDescriptors() {
+    PrintDescriptors(stdout);
+  }
+  void PrintDescriptors(FILE* out);
+#endif
 
+#ifdef DEBUG
   // Is the descriptor array sorted and without duplicates?
   bool IsSortedNoDuplicates();
 
@@ -2396,8 +2451,11 @@ class Dictionary: public HashTable<Shape, Key> {
   // Ensure enough space for n additional elements.
   MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
 
-#ifdef DEBUG
-  void Print();
+#ifdef OBJECT_PRINT
+  inline void Print() {
+    Print(stdout);
+  }
+  void Print(FILE* out);
 #endif
   // Returns the key (slow).
   Object* SlowReverseLookup(Object* value);
@@ -2619,8 +2677,13 @@ class ByteArray: public HeapObject {
   inline int ByteArraySize() {
     return SizeFor(this->length());
   }
+#ifdef OBJECT_PRINT
+  inline void ByteArrayPrint() {
+    ByteArrayPrint(stdout);
+  }
+  void ByteArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ByteArrayPrint();
   void ByteArrayVerify();
 #endif
 
@@ -2669,8 +2732,13 @@ class PixelArray: public HeapObject {
   // Casting.
   static inline PixelArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void PixelArrayPrint() {
+    PixelArrayPrint(stdout);
+  }
+  void PixelArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void PixelArrayPrint();
   void PixelArrayVerify();
 #endif  // DEBUG
 
@@ -2741,8 +2809,13 @@ class ExternalByteArray: public ExternalArray {
   // Casting.
   static inline ExternalByteArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalByteArrayPrint() {
+    ExternalByteArrayPrint(stdout);
+  }
+  void ExternalByteArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalByteArrayPrint();
   void ExternalByteArrayVerify();
 #endif  // DEBUG
 
@@ -2764,8 +2837,13 @@ class ExternalUnsignedByteArray: public ExternalArray {
   // Casting.
   static inline ExternalUnsignedByteArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalUnsignedByteArrayPrint() {
+    ExternalUnsignedByteArrayPrint(stdout);
+  }
+  void ExternalUnsignedByteArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalUnsignedByteArrayPrint();
   void ExternalUnsignedByteArrayVerify();
 #endif  // DEBUG
 
@@ -2787,8 +2865,13 @@ class ExternalShortArray: public ExternalArray {
   // Casting.
   static inline ExternalShortArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalShortArrayPrint() {
+    ExternalShortArrayPrint(stdout);
+  }
+  void ExternalShortArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalShortArrayPrint();
   void ExternalShortArrayVerify();
 #endif  // DEBUG
 
@@ -2810,8 +2893,13 @@ class ExternalUnsignedShortArray: public ExternalArray {
   // Casting.
   static inline ExternalUnsignedShortArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalUnsignedShortArrayPrint() {
+    ExternalUnsignedShortArrayPrint(stdout);
+  }
+  void ExternalUnsignedShortArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalUnsignedShortArrayPrint();
   void ExternalUnsignedShortArrayVerify();
 #endif  // DEBUG
 
@@ -2833,8 +2921,13 @@ class ExternalIntArray: public ExternalArray {
   // Casting.
   static inline ExternalIntArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalIntArrayPrint() {
+    ExternalIntArrayPrint(stdout);
+  }
+  void ExternalIntArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalIntArrayPrint();
   void ExternalIntArrayVerify();
 #endif  // DEBUG
 
@@ -2856,8 +2949,13 @@ class ExternalUnsignedIntArray: public ExternalArray {
   // Casting.
   static inline ExternalUnsignedIntArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalUnsignedIntArrayPrint() {
+    ExternalUnsignedIntArrayPrint(stdout);
+  }
+  void ExternalUnsignedIntArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalUnsignedIntArrayPrint();
   void ExternalUnsignedIntArrayVerify();
 #endif  // DEBUG
 
@@ -2879,8 +2977,13 @@ class ExternalFloatArray: public ExternalArray {
   // Casting.
   static inline ExternalFloatArray* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ExternalFloatArrayPrint() {
+    ExternalFloatArrayPrint(stdout);
+  }
+  void ExternalFloatArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ExternalFloatArrayPrint();
   void ExternalFloatArrayVerify();
 #endif  // DEBUG
 
@@ -2960,8 +3063,8 @@ class DeoptimizationInputData: public FixedArray {
   // Casting.
   static inline DeoptimizationInputData* cast(Object* obj);
 
-#ifdef DEBUG
-  void DeoptimizationInputDataPrint();
+#ifdef OBJECT_PRINT
+  void DeoptimizationInputDataPrint(FILE* out);
 #endif
 
  private:
@@ -2999,8 +3102,8 @@ class DeoptimizationOutputData: public FixedArray {
   // Casting.
   static inline DeoptimizationOutputData* cast(Object* obj);
 
-#ifdef DEBUG
-  void DeoptimizationOutputDataPrint();
+#ifdef OBJECT_PRINT
+  void DeoptimizationOutputDataPrint(FILE* out);
 #endif
 };
 
@@ -3049,7 +3152,10 @@ class Code: public HeapObject {
   static const char* Kind2String(Kind kind);
   static const char* ICState2String(InlineCacheState state);
   static const char* PropertyType2String(PropertyType type);
-  void Disassemble(const char* name);
+  inline void Disassemble(const char* name) {
+    Disassemble(name, stdout);
+  }
+  void Disassemble(const char* name, FILE* out);
 #endif  // ENABLE_DISASSEMBLER
 
   // [instruction_size]: Size of the native instructions
@@ -3242,8 +3348,13 @@ class Code: public HeapObject {
 
   template<typename StaticVisitor>
   inline void CodeIterateBody();
+#ifdef OBJECT_PRINT
+  inline void CodePrint() {
+    CodePrint(stdout);
+  }
+  void CodePrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void CodePrint();
   void CodeVerify();
 #endif
 
@@ -3531,8 +3642,13 @@ class Map: public HeapObject {
   void ClearNonLiveTransitions(Object* real_prototype);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void MapPrint() {
+    MapPrint(stdout);
+  }
+  void MapPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void MapPrint();
   void MapVerify();
   void SharedMapVerify();
 #endif
@@ -3688,8 +3804,13 @@ class Script: public Struct {
   // resource is accessible. Otherwise, always return true.
   inline bool HasValidSource();
 
+#ifdef OBJECT_PRINT
+  inline void ScriptPrint() {
+    ScriptPrint(stdout);
+  }
+  void ScriptPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ScriptPrint();
   void ScriptVerify();
 #endif
 
@@ -4052,8 +4173,13 @@ class SharedFunctionInfo: public HeapObject {
   // Dispatched behavior.
   // Set max_length to -1 for unlimited length.
   void SourceCodePrint(StringStream* accumulator, int max_length);
+#ifdef OBJECT_PRINT
+  inline void SharedFunctionInfoPrint() {
+    SharedFunctionInfoPrint(stdout);
+  }
+  void SharedFunctionInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void SharedFunctionInfoPrint();
   void SharedFunctionInfoVerify();
 #endif
 
@@ -4285,7 +4411,10 @@ class JSFunction: public JSObject {
   DECL_ACCESSORS(next_function_link, Object)
 
   // Prints the name of the function using PrintF.
-  void PrintName();
+  inline void PrintName() {
+    PrintName(stdout);
+  }
+  void PrintName(FILE* out);
 
   // Casting.
   static inline JSFunction* cast(Object* obj);
@@ -4295,8 +4424,13 @@ class JSFunction: public JSObject {
   void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSFunctionPrint() {
+    JSFunctionPrint(stdout);
+  }
+  void JSFunctionPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSFunctionPrint();
   void JSFunctionVerify();
 #endif
 
@@ -4345,8 +4479,13 @@ class JSGlobalProxy : public JSObject {
   static inline JSGlobalProxy* cast(Object* obj);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSGlobalProxyPrint() {
+    JSGlobalProxyPrint(stdout);
+  }
+  void JSGlobalProxyPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSGlobalProxyPrint();
   void JSGlobalProxyVerify();
 #endif
 
@@ -4416,8 +4555,13 @@ class JSGlobalObject: public GlobalObject {
   static inline JSGlobalObject* cast(Object* obj);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSGlobalObjectPrint() {
+    JSGlobalObjectPrint(stdout);
+  }
+  void JSGlobalObjectPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSGlobalObjectPrint();
   void JSGlobalObjectVerify();
 #endif
 
@@ -4445,8 +4589,13 @@ class JSBuiltinsObject: public GlobalObject {
   static inline JSBuiltinsObject* cast(Object* obj);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSBuiltinsObjectPrint() {
+    JSBuiltinsObjectPrint(stdout);
+  }
+  void JSBuiltinsObjectPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSBuiltinsObjectPrint();
   void JSBuiltinsObjectVerify();
 #endif
 
@@ -4483,8 +4632,13 @@ class JSValue: public JSObject {
   static inline JSValue* cast(Object* obj);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSValuePrint() {
+    JSValuePrint(stdout);
+  }
+  void JSValuePrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSValuePrint();
   void JSValueVerify();
 #endif
 
@@ -4673,8 +4827,13 @@ class CodeCache: public Struct {
 
   static inline CodeCache* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void CodeCachePrint() {
+    CodeCachePrint(stdout);
+  }
+  void CodeCachePrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void CodeCachePrint();
   void CodeCacheVerify();
 #endif
 
@@ -4975,8 +5134,13 @@ class String: public HeapObject {
 
   // Dispatched behavior.
   void StringShortPrint(StringStream* accumulator);
+#ifdef OBJECT_PRINT
+  inline void StringPrint() {
+    StringPrint(stdout);
+  }
+  void StringPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void StringPrint();
   void StringVerify();
 #endif
   inline bool IsFlat();
@@ -5531,7 +5695,12 @@ class JSGlobalPropertyCell: public HeapObject {
 
 #ifdef DEBUG
   void JSGlobalPropertyCellVerify();
-  void JSGlobalPropertyCellPrint();
+#endif
+#ifdef OBJECT_PRINT
+  inline void JSGlobalPropertyCellPrint() {
+    JSGlobalPropertyCellPrint(stdout);
+  }
+  void JSGlobalPropertyCellPrint(FILE* out);
 #endif
 
   // Layout description.
@@ -5566,8 +5735,13 @@ class Proxy: public HeapObject {
   template<typename StaticVisitor>
   inline void ProxyIterateBody();
 
+#ifdef OBJECT_PRINT
+  inline void ProxyPrint() {
+    ProxyPrint(stdout);
+  }
+  void ProxyPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ProxyPrint();
   void ProxyVerify();
 #endif
 
@@ -5616,8 +5790,13 @@ class JSArray: public JSObject {
   inline void EnsureSize(int minimum_size_of_backing_fixed_array);
 
   // Dispatched behavior.
+#ifdef OBJECT_PRINT
+  inline void JSArrayPrint() {
+    JSArrayPrint(stdout);
+  }
+  void JSArrayPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void JSArrayPrint();
   void JSArrayVerify();
 #endif
 
@@ -5688,8 +5867,13 @@ class AccessorInfo: public Struct {
 
   static inline AccessorInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void AccessorInfoPrint() {
+    AccessorInfoPrint(stdout);
+  }
+  void AccessorInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void AccessorInfoPrint();
   void AccessorInfoVerify();
 #endif
 
@@ -5719,8 +5903,13 @@ class AccessCheckInfo: public Struct {
 
   static inline AccessCheckInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void AccessCheckInfoPrint() {
+    AccessCheckInfoPrint(stdout);
+  }
+  void AccessCheckInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void AccessCheckInfoPrint();
   void AccessCheckInfoVerify();
 #endif
 
@@ -5745,8 +5934,13 @@ class InterceptorInfo: public Struct {
 
   static inline InterceptorInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void InterceptorInfoPrint() {
+    InterceptorInfoPrint(stdout);
+  }
+  void InterceptorInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void InterceptorInfoPrint();
   void InterceptorInfoVerify();
 #endif
 
@@ -5770,8 +5964,13 @@ class CallHandlerInfo: public Struct {
 
   static inline CallHandlerInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void CallHandlerInfoPrint() {
+    CallHandlerInfoPrint(stdout);
+  }
+  void CallHandlerInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void CallHandlerInfoPrint();
   void CallHandlerInfoVerify();
 #endif
 
@@ -5827,8 +6026,13 @@ class FunctionTemplateInfo: public TemplateInfo {
 
   static inline FunctionTemplateInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void FunctionTemplateInfoPrint() {
+    FunctionTemplateInfoPrint(stdout);
+  }
+  void FunctionTemplateInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void FunctionTemplateInfoPrint();
   void FunctionTemplateInfoVerify();
 #endif
 
@@ -5870,8 +6074,13 @@ class ObjectTemplateInfo: public TemplateInfo {
 
   static inline ObjectTemplateInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void ObjectTemplateInfoPrint() {
+    ObjectTemplateInfoPrint(stdout);
+  }
+  void ObjectTemplateInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void ObjectTemplateInfoPrint();
   void ObjectTemplateInfoVerify();
 #endif
 
@@ -5889,8 +6098,13 @@ class SignatureInfo: public Struct {
 
   static inline SignatureInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void SignatureInfoPrint() {
+    SignatureInfoPrint(stdout);
+  }
+  void SignatureInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void SignatureInfoPrint();
   void SignatureInfoVerify();
 #endif
 
@@ -5909,8 +6123,13 @@ class TypeSwitchInfo: public Struct {
 
   static inline TypeSwitchInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void TypeSwitchInfoPrint() {
+    TypeSwitchInfoPrint(stdout);
+  }
+  void TypeSwitchInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void TypeSwitchInfoPrint();
   void TypeSwitchInfoVerify();
 #endif
 
@@ -5956,8 +6175,13 @@ class DebugInfo: public Struct {
 
   static inline DebugInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void DebugInfoPrint() {
+    DebugInfoPrint(stdout);
+  }
+  void DebugInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void DebugInfoPrint();
   void DebugInfoVerify();
 #endif
 
@@ -6009,8 +6233,13 @@ class BreakPointInfo: public Struct {
 
   static inline BreakPointInfo* cast(Object* obj);
 
+#ifdef OBJECT_PRINT
+  inline void BreakPointInfoPrint() {
+    BreakPointInfoPrint(stdout);
+  }
+  void BreakPointInfoPrint(FILE* out);
+#endif
 #ifdef DEBUG
-  void BreakPointInfoPrint();
   void BreakPointInfoVerify();
 #endif
 
index 94ad57c..08f77b8 100644 (file)
@@ -3730,7 +3730,7 @@ RegExpParser::RegExpParser(FlatStringReader* in,
     contains_anchor_(false),
     is_scanned_for_captures_(false),
     failed_(false) {
-  Advance(1);
+  Advance();
 }
 
 
@@ -3768,8 +3768,8 @@ void RegExpParser::Reset(int pos) {
 
 
 void RegExpParser::Advance(int dist) {
-  for (int i = 0; i < dist; i++)
-    Advance();
+  next_pos_ += dist - 1;
+  Advance();
 }
 
 
index f34483d..72ea0e5 100644 (file)
@@ -128,6 +128,19 @@ void OS::VPrint(const char* format, va_list args) {
 }
 
 
+void OS::FPrint(FILE* out, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VFPrint(out, format, args);
+  va_end(args);
+}
+
+
+void OS::VFPrint(FILE* out, const char* format, va_list args) {
+  vfprintf(out, format, args);
+}
+
+
 // Print error message to console.
 void OS::PrintError(const char* format, ...) {
   // Minimalistic implementation for bootstrapping.
index c50d396..ab5c0a3 100644 (file)
@@ -142,6 +142,23 @@ void OS::VPrint(const char* format, va_list args) {
 }
 
 
+void OS::FPrint(FILE* out, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VFPrint(out, format, args);
+  va_end(args);
+}
+
+
+void OS::VFPrint(FILE* out, const char* format, va_list args) {
+#if defined(ANDROID)
+  LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
+#else
+  vfprintf(out, format, args);
+#endif
+}
+
+
 void OS::PrintError(const char* format, ...) {
   va_list args;
   va_start(args, format);
@@ -173,7 +190,9 @@ int OS::VSNPrintF(Vector<char> str,
                   va_list args) {
   int n = vsnprintf(str.start(), str.length(), format, args);
   if (n < 0 || n >= str.length()) {
-    str[str.length() - 1] = '\0';
+    // If the length is zero, the assignment fails.
+    if (str.length() > 0)
+      str[str.length() - 1] = '\0';
     return -1;
   } else {
     return n;
@@ -204,6 +223,14 @@ class POSIXSocket : public Socket {
   explicit POSIXSocket() {
     // Create the socket.
     socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (IsValid()) {
+      // Allow rapid reuse.
+      static const int kOn = 1;
+      int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
+                           &kOn, sizeof(kOn));
+      ASSERT(ret == 0);
+      USE(ret);
+    }
   }
   explicit POSIXSocket(int socket): socket_(socket) { }
   virtual ~POSIXSocket() { Shutdown(); }
index badc31b..4438045 100644 (file)
@@ -688,6 +688,19 @@ void OS::VPrint(const char* format, va_list args) {
 }
 
 
+void OS::FPrint(FILE* out, const char* format, ...) {
+  va_list args;
+  va_start(args, format);
+  VFPrint(out, format, args);
+  va_end(args);
+}
+
+
+void OS::VFPrint(FILE* out, const char* format, va_list args) {
+  VPrintHelper(out, format, args);
+}
+
+
 // Print error message to console.
 void OS::PrintError(const char* format, ...) {
   va_list args;
@@ -716,7 +729,8 @@ int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) {
   // Make sure to zero-terminate the string if the output was
   // truncated or if there was an error.
   if (n < 0 || n >= str.length()) {
-    str[str.length() - 1] = '\0';
+    if (str.length() > 0)
+      str[str.length() - 1] = '\0';
     return -1;
   } else {
     return n;
index 690f83c..bdfbbab 100644 (file)
@@ -184,6 +184,10 @@ class OS {
   static void Print(const char* format, ...);
   static void VPrint(const char* format, va_list args);
 
+  // Print output to a file. This is mostly used for debugging output.
+  static void FPrint(FILE* out, const char* format, ...);
+  static void VFPrint(FILE* out, const char* format, va_list args);
+
   // Print error output to console. This is mostly used for error message
   // output. On platforms that has standard terminal output, the output
   // should go to stderr.
index 364f51d..34d1877 100644 (file)
@@ -2218,7 +2218,7 @@ void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) {
 void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
   if (control_ == NULL) return;
 
-  HeapIterator iterator(HeapIterator::kPreciseFiltering);
+  HeapIterator iterator(HeapIterator::kFilterUnreachable);
   int objects_count = 0;
   for (HeapObject* obj = iterator.next();
        obj != NULL;
@@ -2342,8 +2342,6 @@ bool HeapSnapshotGenerator::SetEntriesDominators() {
     ASSERT(dominators[i] != NULL);
     ordered_entries[i]->set_dominator(dominators[i]);
   }
-  // For nodes unreachable from root, set dominator to itself.
-  snapshot_->SetDominatorsToSelf();
   return true;
 }
 
@@ -2373,9 +2371,9 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
 
 
 bool HeapSnapshotGenerator::IterateAndExtractReferences() {
-  HeapIterator iterator(HeapIterator::kPreciseFiltering);
+  HeapIterator iterator(HeapIterator::kFilterUnreachable);
   bool interrupted = false;
-  // Heap iteration with precise filtering must be finished in any case.
+  // Heap iteration with filtering must be finished in any case.
   for (HeapObject* obj = iterator.next();
        obj != NULL;
        obj = iterator.next(), IncProgressCounter()) {
index b579b68..9677433 100644 (file)
@@ -31,62 +31,62 @@ namespace v8 {
 namespace internal {
 
 
-#ifdef DEBUG
-void LookupResult::Print() {
+#ifdef OBJECT_PRINT
+void LookupResult::Print(FILE* out) {
   if (!IsFound()) {
-    PrintF("Not Found\n");
+    PrintF(out, "Not Found\n");
     return;
   }
 
-  PrintF("LookupResult:\n");
-  PrintF(" -cacheable = %s\n", IsCacheable() ? "true" : "false");
-  PrintF(" -attributes = %x\n", GetAttributes());
+  PrintF(out, "LookupResult:\n");
+  PrintF(out, " -cacheable = %s\n", IsCacheable() ? "true" : "false");
+  PrintF(out, " -attributes = %x\n", GetAttributes());
   switch (type()) {
     case NORMAL:
-      PrintF(" -type = normal\n");
-      PrintF(" -entry = %d", GetDictionaryEntry());
+      PrintF(out, " -type = normal\n");
+      PrintF(out, " -entry = %d", GetDictionaryEntry());
       break;
     case MAP_TRANSITION:
-      PrintF(" -type = map transition\n");
-      PrintF(" -map:\n");
-      GetTransitionMap()->Print();
-      PrintF("\n");
+      PrintF(out, " -type = map transition\n");
+      PrintF(out, " -map:\n");
+      GetTransitionMap()->Print(out);
+      PrintF(out, "\n");
       break;
     case CONSTANT_FUNCTION:
-      PrintF(" -type = constant function\n");
-      PrintF(" -function:\n");
-      GetConstantFunction()->Print();
-      PrintF("\n");
+      PrintF(out, " -type = constant function\n");
+      PrintF(out, " -function:\n");
+      GetConstantFunction()->Print(out);
+      PrintF(out, "\n");
       break;
     case FIELD:
-      PrintF(" -type = field\n");
-      PrintF(" -index = %d", GetFieldIndex());
-      PrintF("\n");
+      PrintF(out, " -type = field\n");
+      PrintF(out, " -index = %d", GetFieldIndex());
+      PrintF(out, "\n");
       break;
     case CALLBACKS:
-      PrintF(" -type = call backs\n");
-      PrintF(" -callback object:\n");
-      GetCallbackObject()->Print();
+      PrintF(out, " -type = call backs\n");
+      PrintF(out, " -callback object:\n");
+      GetCallbackObject()->Print(out);
       break;
     case INTERCEPTOR:
-      PrintF(" -type = lookup interceptor\n");
+      PrintF(out, " -type = lookup interceptor\n");
       break;
     case CONSTANT_TRANSITION:
-      PrintF(" -type = constant property transition\n");
+      PrintF(out, " -type = constant property transition\n");
       break;
     case NULL_DESCRIPTOR:
-      PrintF(" =type = null descriptor\n");
+      PrintF(out, " =type = null descriptor\n");
       break;
   }
 }
 
 
-void Descriptor::Print() {
-  PrintF("Descriptor ");
-  GetKey()->ShortPrint();
-  PrintF(" @ ");
-  GetValue()->ShortPrint();
-  PrintF(" %d\n", GetDetails().index());
+void Descriptor::Print(FILE* out) {
+  PrintF(out, "Descriptor ");
+  GetKey()->ShortPrint(out);
+  PrintF(out, " @ ");
+  GetValue()->ShortPrint(out);
+  PrintF(out, " %d\n", GetDetails().index());
 }
 
 
index 537b4e6..c39fe41 100644 (file)
@@ -60,8 +60,8 @@ class Descriptor BASE_EMBEDDED {
   Object* GetValue() { return value_; }
   PropertyDetails GetDetails() { return details_; }
 
-#ifdef DEBUG
-  void Print();
+#ifdef OBJECT_PRINT
+  void Print(FILE* out);
 #endif
 
   void SetEnumerationIndex(int index) {
@@ -310,8 +310,8 @@ class LookupResult BASE_EMBEDDED {
     return GetValue();
   }
 
-#ifdef DEBUG
-  void Print();
+#ifdef OBJECT_PRINT
+  void Print(FILE* out);
 #endif
 
   Object* GetValue() {
index dd27266..0de66c6 100644 (file)
@@ -32,7 +32,7 @@ const $RegExp = global.RegExp;
 
 // A recursive descent parser for Patterns according to the grammar of
 // ECMA-262 15.10.1, with deviations noted below.
-function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
+function DoConstructRegExp(object, pattern, flags) {
   // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
   if (IS_REGEXP(pattern)) {
     if (!IS_UNDEFINED(flags)) {
@@ -80,7 +80,7 @@ function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
 
 function RegExpConstructor(pattern, flags) {
   if (%_IsConstructCall()) {
-    DoConstructRegExp(this, pattern, flags, true);
+    DoConstructRegExp(this, pattern, flags);
   } else {
     // RegExp : Called as function; see ECMA-262, section 15.10.3.1.
     if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) {
@@ -104,9 +104,9 @@ function CompileRegExp(pattern, flags) {
   // the empty string.  For compatibility with JSC, we match their
   // behavior.
   if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
-    DoConstructRegExp(this, 'undefined', flags, false);
+    DoConstructRegExp(this, 'undefined', flags);
   } else {
-    DoConstructRegExp(this, pattern, flags, false);
+    DoConstructRegExp(this, pattern, flags);
   }
 }
 
@@ -150,12 +150,12 @@ function BuildResultFromMatchInfo(lastMatchInfo, s) {
 
 function RegExpExecNoTests(regexp, string, start) {
   // Must be called with RegExp, string and positive integer as arguments.
-  var matchInfo = DoRegExpExec(regexp, string, start);
-  var result = null;
+  var matchInfo = %_RegExpExec(regexp, string, start, lastMatchInfo);
   if (matchInfo !== null) {
-    result = BuildResultFromMatchInfo(matchInfo, string);
+    lastMatchInfoOverride = null;
+    return BuildResultFromMatchInfo(matchInfo, string);
   }
-  return result;
+  return null;
 }
 
 
@@ -261,11 +261,14 @@ function RegExpTest(string) {
         %_StringCharCodeAt(this.source, 2) != 63) {  // '?'
       if (!%_ObjectEquals(regexp_key, this)) {
         regexp_key = this;
-        regexp_val = new $RegExp(this.source.substring(2, this.source.length),
-                                 (this.ignoreCase ? 'i' : '')
-                                 + (this.multiline ? 'm' : ''));
+        regexp_val = new $RegExp(SubString(this.source, 2, this.source.length),
+                                 (!this.ignoreCase 
+                                  ? !this.multiline ? "" : "m"
+                                  : !this.multiline ? "i" : "im"));
+      }
+      if (%_RegExpExec(regexp_val, string, 0, lastMatchInfo) === null) {
+        return false;
       }
-      if (!regexp_val.test(string)) return false;
     }    
     %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
     // matchIndices is either null or the lastMatchInfo array.
index 0fd2f8b..724a436 100644 (file)
@@ -7204,7 +7204,7 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
   // extension object itself.
   if ((attributes & READ_ONLY) == 0 ||
       (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
-    Handle<Object> set = SetProperty(context_ext, name, value, attributes);
+    Handle<Object> set = SetProperty(context_ext, name, value, NONE);
     if (set.is_null()) {
       // Failure::Exception is converted to a null handle in the
       // handle-based methods such as SetProperty.  We therefore need
index 8e9d889..fca1032 100644 (file)
@@ -364,15 +364,15 @@ void MemoryAllocator::TearDown() {
 }
 
 
-void MemoryAllocator::FreeChunkTables(AtomicWord* array, int len, int level) {
+void MemoryAllocator::FreeChunkTables(uintptr_t* array, int len, int level) {
   for (int i = 0; i < len; i++) {
     if (array[i] != kUnusedChunkTableEntry) {
-      AtomicWord* subarray = reinterpret_cast<AtomicWord*>(array[i]);
+      uintptr_t* subarray = reinterpret_cast<uintptr_t*>(array[i]);
       if (level > 1) {
-        Release_Store(&array[i], kUnusedChunkTableEntry);
+        array[i] = kUnusedChunkTableEntry;
         FreeChunkTables(subarray, 1 << kChunkTableBitsPerLevel, level - 1);
       } else {
-        Release_Store(&array[i], kUnusedChunkTableEntry);
+        array[i] = kUnusedChunkTableEntry;
       }
       delete[] subarray;
     }
@@ -822,7 +822,7 @@ void MemoryAllocator::AddToAllocatedChunks(Address addr, intptr_t size) {
 
 void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
                                            uintptr_t chunk_index_base) {
-  AtomicWord* fine_grained = AllocatedChunksFinder(
+  uintptr_t* fine_grained = AllocatedChunksFinder(
       chunk_table_,
       chunk_index_base,
       kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@@ -830,7 +830,7 @@ void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
   int index = FineGrainedIndexForAddress(chunk_index_base);
   if (fine_grained[index] != kUnusedChunkTableEntry) index++;
   ASSERT(fine_grained[index] == kUnusedChunkTableEntry);
-  Release_Store(&fine_grained[index], chunk_start);
+  fine_grained[index] = chunk_start;
 }
 
 
@@ -845,7 +845,7 @@ void MemoryAllocator::RemoveFromAllocatedChunks(Address addr, intptr_t size) {
 void MemoryAllocator::RemoveChunkFoundUsingAddress(
     uintptr_t chunk_start,
     uintptr_t chunk_index_base) {
-  AtomicWord* fine_grained = AllocatedChunksFinder(
+  uintptr_t* fine_grained = AllocatedChunksFinder(
       chunk_table_,
       chunk_index_base,
       kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@@ -854,22 +854,23 @@ void MemoryAllocator::RemoveChunkFoundUsingAddress(
   ASSERT(fine_grained != kUnusedChunkTableEntry);
   int index = FineGrainedIndexForAddress(chunk_index_base);
   ASSERT(fine_grained[index] != kUnusedChunkTableEntry);
-  if (fine_grained[index] != static_cast<AtomicWord>(chunk_start)) {
+  if (fine_grained[index] != chunk_start) {
     index++;
-    ASSERT(fine_grained[index] == static_cast<AtomicWord>(chunk_start));
-    Release_Store(&fine_grained[index], kUnusedChunkTableEntry);
+    ASSERT(fine_grained[index] == chunk_start);
+    fine_grained[index] = kUnusedChunkTableEntry;
   } else {
-    Release_Store(&fine_grained[index], fine_grained[index + 1]);
-    // Here for a moment the two entries are duplicates, but the reader can
-    // handle that.
-    NoBarrier_Store(&fine_grained[index + 1], kUnusedChunkTableEntry);
+    // If only one of the entries is used it must be the first, since
+    // InAllocatedChunks relies on that.  Move things around so that this is
+    // the case.
+    fine_grained[index] = fine_grained[index + 1];
+    fine_grained[index + 1] = kUnusedChunkTableEntry;
   }
 }
 
 
 bool MemoryAllocator::InAllocatedChunks(Address addr) {
   uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
-  AtomicWord* fine_grained = AllocatedChunksFinder(
+  uintptr_t* fine_grained = AllocatedChunksFinder(
       chunk_table_,
       int_address,
       kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@@ -877,21 +878,18 @@ bool MemoryAllocator::InAllocatedChunks(Address addr) {
   if (fine_grained == NULL) return false;
   int index = FineGrainedIndexForAddress(int_address);
   if (fine_grained[index] == kUnusedChunkTableEntry) return false;
-  uintptr_t entry = static_cast<uintptr_t>(fine_grained[index]);
+  uintptr_t entry = fine_grained[index];
   if (entry <= int_address && entry + kChunkSize > int_address) return true;
   index++;
   if (fine_grained[index] == kUnusedChunkTableEntry) return false;
-  entry = static_cast<uintptr_t>(fine_grained[index]);
-  // At this point it would seem that we must have a hit, but there is a small
-  // window during RemoveChunkFoundUsingAddress where the two entries are
-  // duplicates and we have to handle that.
+  entry = fine_grained[index];
   if (entry <= int_address && entry + kChunkSize > int_address) return true;
   return false;
 }
 
 
-AtomicWord* MemoryAllocator::AllocatedChunksFinder(
-    AtomicWord* table,
+uintptr_t* MemoryAllocator::AllocatedChunksFinder(
+    uintptr_t* table,
     uintptr_t address,
     int bit_position,
     CreateTables create_as_needed) {
@@ -906,8 +904,8 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
       address & ((V8_INTPTR_C(1) << bit_position) - 1);
   ASSERT((table == chunk_table_ && index < kChunkTableTopLevelEntries) ||
          (table != chunk_table_ && index < 1 << kChunkTableBitsPerLevel));
-  AtomicWord* more_fine_grained_table =
-      reinterpret_cast<AtomicWord*>(table[index]);
+  uintptr_t* more_fine_grained_table =
+      reinterpret_cast<uintptr_t*>(table[index]);
   if (more_fine_grained_table == kUnusedChunkTableEntry) {
     if (create_as_needed == kDontCreateTables) return NULL;
     int words_needed = 1 << kChunkTableBitsPerLevel;
@@ -915,12 +913,11 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
       words_needed =
           (1 << kChunkTableBitsPerLevel) * kChunkTableFineGrainedWordsPerEntry;
     }
-    more_fine_grained_table = new AtomicWord[words_needed];
+    more_fine_grained_table = new uintptr_t[words_needed];
     for (int i = 0; i < words_needed; i++) {
       more_fine_grained_table[i] = kUnusedChunkTableEntry;
     }
-    Release_Store(&table[index],
-                  reinterpret_cast<AtomicWord>(more_fine_grained_table));
+    table[index] = reinterpret_cast<uintptr_t>(more_fine_grained_table);
   }
   return AllocatedChunksFinder(
       more_fine_grained_table,
@@ -930,7 +927,7 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
 }
 
 
-AtomicWord MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
+uintptr_t MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
 
 
 // -----------------------------------------------------------------------------
index 2c17ef0..4f2d07b 100644 (file)
@@ -28,7 +28,6 @@
 #ifndef V8_SPACES_H_
 #define V8_SPACES_H_
 
-#include "atomicops.h"
 #include "list-inl.h"
 #include "log.h"
 
@@ -688,7 +687,7 @@ class MemoryAllocator : public AllStatic {
   // The chunks are not chunk-size aligned so for a given chunk-sized area of
   // memory there can be two chunks that cover it.
   static const int kChunkTableFineGrainedWordsPerEntry = 2;
-  static const AtomicWord kUnusedChunkTableEntry = 0;
+  static const uintptr_t kUnusedChunkTableEntry = 0;
 
   // Maximum space size in bytes.
   static intptr_t capacity_;
@@ -696,7 +695,7 @@ class MemoryAllocator : public AllStatic {
   static intptr_t capacity_executable_;
 
   // Top level table to track whether memory is part of a chunk or not.
-  static AtomicWord chunk_table_[kChunkTableTopLevelEntries];
+  static uintptr_t chunk_table_[kChunkTableTopLevelEntries];
 
   // Allocated space size in bytes.
   static intptr_t size_;
@@ -766,11 +765,11 @@ class MemoryAllocator : public AllStatic {
   // Controls whether the lookup creates intermediate levels of tables as
   // needed.
   enum CreateTables { kDontCreateTables, kCreateTablesAsNeeded };
-  static AtomicWord* AllocatedChunksFinder(AtomicWord* table,
-                                           uintptr_t address,
-                                           int bit_position,
-                                           CreateTables create_as_needed);
-  static void FreeChunkTables(AtomicWord* array, int length, int level);
+  static uintptr_t* AllocatedChunksFinder(uintptr_t* table,
+                                          uintptr_t address,
+                                          int bit_position,
+                                          CreateTables create_as_needed);
+  static void FreeChunkTables(uintptr_t* array, int length, int level);
   static int FineGrainedIndexForAddress(uintptr_t address) {
     int index = ((address >> kChunkSizeLog2) &
         ((1 << kChunkTableBitsPerLevel) - 1));
index d1859a2..7abd1bb 100644 (file)
@@ -264,7 +264,7 @@ void StringStream::Log() {
 }
 
 
-void StringStream::OutputToStdOut() {
+void StringStream::OutputToFile(FILE* out) {
   // Dump the output to stdout, but make sure to break it up into
   // manageable chunks to avoid losing parts of the output in the OS
   // printing code. This is a problem on Windows in particular; see
@@ -273,10 +273,10 @@ void StringStream::OutputToStdOut() {
   for (unsigned next; (next = position + 2048) < length_; position = next) {
     char save = buffer_[next];
     buffer_[next] = '\0';
-    internal::PrintF("%s", &buffer_[position]);
+    internal::PrintF(out, "%s", &buffer_[position]);
     buffer_[next] = save;
   }
-  internal::PrintF("%s", &buffer_[position]);
+  internal::PrintF(out, "%s", &buffer_[position]);
 }
 
 
index b74c793..b3f2e0d 100644 (file)
@@ -138,7 +138,8 @@ class StringStream {
            FmtElm arg3);
 
   // Getting the message out.
-  void OutputToStdOut();
+  void OutputToFile(FILE* out);
+  void OutputToStdOut() { OutputToFile(stdout); }
   void Log();
   Handle<String> ToString();
   SmartPointer<const char> ToCString() const;
index 6d4e0c1..9527599 100644 (file)
@@ -159,7 +159,7 @@ function StringLocaleCompare(other) {
 function StringMatch(regexp) {
   var subject = TO_STRING_INLINE(this);
   if (IS_REGEXP(regexp)) {
-    if (!regexp.global) return regexp.exec(subject);
+    if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0);
     %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
     // lastMatchInfo is defined in regexp.js.
     return %StringMatch(subject, regexp, lastMatchInfo);
@@ -245,17 +245,18 @@ function StringReplace(search, replace) {
 // Expand the $-expressions in the string and return a new string with
 // the result.
 function ExpandReplacement(string, subject, matchInfo, builder) {
+  var length = string.length;
+  var builder_elements = builder.elements; 
   var next = %StringIndexOf(string, '$', 0);
   if (next < 0) {
-    builder.add(string);
+    if (length > 0) builder_elements.push(string);
     return;
   }
 
   // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
   var m = NUMBER_OF_CAPTURES(matchInfo) >> 1;  // Includes the match.
 
-  if (next > 0) builder.add(SubString(string, 0, next));
-  var length = string.length;
+  if (next > 0) builder_elements.push(SubString(string, 0, next));
 
   while (true) {
     var expansion = '$';
@@ -264,7 +265,7 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
       var peek = %_StringCharCodeAt(string, position);
       if (peek == 36) {         // $$
         ++position;
-        builder.add('$');
+        builder_elements.push('$');
       } else if (peek == 38) {  // $& - match
         ++position;
         builder.addSpecialSlice(matchInfo[CAPTURE0],
@@ -301,14 +302,14 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
           // digit capture references, we can only enter here when a
           // single digit capture reference is outside the range of
           // captures.
-          builder.add('$');
+          builder_elements.push('$');
           --position;
         }
       } else {
-        builder.add('$');
+        builder_elements.push('$');
       }
     } else {
-      builder.add('$');
+      builder_elements.push('$');
     }
 
     // Go the the next $ in the string.
@@ -318,13 +319,15 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
     // haven't reached the end, we need to append the suffix.
     if (next < 0) {
       if (position < length) {
-        builder.add(SubString(string, position, length));
+        builder_elements.push(SubString(string, position, length));
       }
       return;
     }
 
     // Append substring between the previous and the next $ character.
-    builder.add(SubString(string, position, next));
+    if (next > position) {
+      builder_elements.push(SubString(string, position, next));
+    }
   }
 };
 
@@ -559,23 +562,22 @@ function StringSplit(separator, limit) {
 
   var currentIndex = 0;
   var startIndex = 0;
+  var startMatch = 0;
   var result = [];
 
   outer_loop:
   while (true) {
 
     if (startIndex === length) {
-      result.push(subject.slice(currentIndex, length));
+      result.push(SubString(subject, currentIndex, length));
       break;
     }
 
-    var matchInfo = splitMatch(separator, subject, currentIndex, startIndex);
-
-    if (IS_NULL(matchInfo)) {
-      result.push(subject.slice(currentIndex, length));
+    var matchInfo = DoRegExpExec(separator, subject, startIndex);
+    if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
+      result.push(SubString(subject, currentIndex, length));
       break;
     }
-
     var endIndex = matchInfo[CAPTURE1];
 
     // We ignore a zero-length match at the currentIndex.
@@ -584,7 +586,12 @@ function StringSplit(separator, limit) {
       continue;
     }
 
-    result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0]));
+    if (currentIndex + 1 == startMatch) {
+      result.push(%_StringCharAt(subject, currentIndex));
+    } else {
+      result.push(%_SubString(subject, currentIndex, startMatch));
+    }
+
     if (result.length === limit) break;
 
     var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
@@ -609,19 +616,6 @@ function StringSplit(separator, limit) {
 }
 
 
-// ECMA-262 section 15.5.4.14
-// Helper function used by split.  This version returns the matchInfo
-// instead of allocating a new array with basically the same information.
-function splitMatch(separator, subject, current_index, start_index) {
-  var matchInfo = DoRegExpExec(separator, subject, start_index);
-  if (matchInfo == null) return null;
-  // Section 15.5.4.14 paragraph two says that we do not allow zero length
-  // matches at the end of the string.
-  if (matchInfo[CAPTURE0] === subject.length) return null;
-  return matchInfo;
-}
-
-
 // ECMA-262 section 15.5.4.15
 function StringSubstring(start, end) {
   var s = TO_STRING_INLINE(this);
@@ -844,24 +838,21 @@ function ReplaceResultBuilder(str) {
 
 ReplaceResultBuilder.prototype.add = function(str) {
   str = TO_STRING_INLINE(str);
-  if (str.length > 0) {
-    var elements = this.elements;
-    elements[elements.length] = str;
-  }
+  if (str.length > 0) this.elements.push(str);
 }
 
 
 ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
   var len = end - start;
   if (start < 0 || len <= 0) return;
-  var elements = this.elements;
   if (start < 0x80000 && len < 0x800) {
-    elements[elements.length] = (start << 11) | len;
+    this.elements.push((start << 11) | len);
   } else {
     // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
     // so -len is a smi.
-    elements[elements.length] = -len;
-    elements[elements.length] = start;
+    var elements = this.elements;
+    elements.push(-len);
+    elements.push(start);
   }
 }
 
index 2c234bb..d0ec4ef 100644 (file)
@@ -45,8 +45,16 @@ void PrintF(const char* format, ...) {
 }
 
 
-void Flush() {
-  fflush(stdout);
+void PrintF(FILE* out, const char* format, ...) {
+  va_list arguments;
+  va_start(arguments, format);
+  OS::VFPrint(out, format, arguments);
+  va_end(arguments);
+}
+
+
+void Flush(FILE* out) {
+  fflush(out);
 }
 
 
index a5cf42e..fa5d581 100644 (file)
@@ -28,7 +28,9 @@
 #ifndef V8_V8_COUNTERS_H_
 #define V8_V8_COUNTERS_H_
 
+#include "allocation.h"
 #include "counters.h"
+#include "v8globals.h"
 
 namespace v8 {
 namespace internal {
index 59b3898..b000d14 100644 (file)
@@ -43,18 +43,26 @@ namespace internal {
 // so it works on MacOSX.
 #if defined(__MACH__) && defined(__APPLE__)
 #define PRINTF_CHECKING
+#define FPRINTF_CHECKING
 #else  // MacOsX.
 #define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
+#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
 #endif
 #else
 #define PRINTF_CHECKING
+#define FPRINTF_CHECKING
 #endif
 
 // Our version of printf().
 void PRINTF_CHECKING PrintF(const char* format, ...);
+void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
 
 // Our version of fflush.
-void Flush();
+void Flush(FILE* out);
+
+inline void Flush() {
+  Flush(stdout);
+}
 
 
 // Read a line of characters after printing the prompt to stdout. The resulting
index 60e61b1..d2c0960 100644 (file)
@@ -34,8 +34,8 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     0
-#define BUILD_NUMBER      3
-#define PATCH_LEVEL       0
+#define BUILD_NUMBER      4
+#define PATCH_LEVEL       1
 #define CANDIDATE_VERSION false
 
 // Define SONAME to have the SCons build the put a specific SONAME into the
index 6c8b333..9a25572 100644 (file)
@@ -6784,9 +6784,9 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
 
   // Check that both indices are valid.
   __ movq(tmp2.reg(), FieldOperand(object.reg(), JSArray::kLengthOffset));
-  __ cmpl(tmp2.reg(), index1.reg());
+  __ SmiCompare(tmp2.reg(), index1.reg());
   deferred->Branch(below_equal);
-  __ cmpl(tmp2.reg(), index2.reg());
+  __ SmiCompare(tmp2.reg(), index2.reg());
   deferred->Branch(below_equal);
 
   // Bring addresses into index1 and index2.
index aa5fe59..a23ee17 100644 (file)
@@ -1216,7 +1216,7 @@ TEST(TestInternalWeakListsTraverseWithGC) {
 TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
   InitializeVM();
   intptr_t size_of_objects_1 = Heap::SizeOfObjects();
-  HeapIterator iterator(HeapIterator::kPreciseFiltering);
+  HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
   intptr_t size_of_objects_2 = 0;
   for (HeapObject* obj = iterator.next();
        obj != NULL;
@@ -1240,3 +1240,65 @@ TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
     CHECK_GT(size_of_objects_2 / 100, delta);
   }
 }
+
+
+class HeapIteratorTestHelper {
+ public:
+  HeapIteratorTestHelper(Object* a, Object* b)
+      : a_(a), b_(b), a_found_(false), b_found_(false) {}
+  bool a_found() { return a_found_; }
+  bool b_found() { return b_found_; }
+  void IterateHeap(HeapIterator::HeapObjectsFiltering mode) {
+    HeapIterator iterator(mode);
+    for (HeapObject* obj = iterator.next();
+         obj != NULL;
+         obj = iterator.next()) {
+      if (obj == a_)
+        a_found_ = true;
+      else if (obj == b_)
+        b_found_ = true;
+    }
+  }
+ private:
+  Object* a_;
+  Object* b_;
+  bool a_found_;
+  bool b_found_;
+};
+
+TEST(HeapIteratorFilterUnreachable) {
+  InitializeVM();
+  v8::HandleScope scope;
+  CompileRun("a = {}; b = {};");
+  v8::Handle<Object> a(Top::context()->global()->GetProperty(
+      *Factory::LookupAsciiSymbol("a"))->ToObjectChecked());
+  v8::Handle<Object> b(Top::context()->global()->GetProperty(
+      *Factory::LookupAsciiSymbol("b"))->ToObjectChecked());
+  CHECK_NE(*a, *b);
+  {
+    HeapIteratorTestHelper helper(*a, *b);
+    helper.IterateHeap(HeapIterator::kFilterUnreachable);
+    CHECK(helper.a_found());
+    CHECK(helper.b_found());
+  }
+  CHECK(Top::context()->global()->DeleteProperty(
+      *Factory::LookupAsciiSymbol("a"), JSObject::FORCE_DELETION));
+  // We ensure that GC will not happen, so our raw pointer stays valid.
+  AssertNoAllocation no_alloc;
+  Object* a_saved = *a;
+  a.Clear();
+  // Verify that "a" object still resides in the heap...
+  {
+    HeapIteratorTestHelper helper(a_saved, *b);
+    helper.IterateHeap(HeapIterator::kNoFiltering);
+    CHECK(helper.a_found());
+    CHECK(helper.b_found());
+  }
+  // ...but is now unreachable.
+  {
+    HeapIteratorTestHelper helper(a_saved, *b);
+    helper.IterateHeap(HeapIterator::kFilterUnreachable);
+    CHECK(!helper.a_found());
+    CHECK(helper.b_found());
+  }
+}
index 8f9ce53..50b5b27 100644 (file)
     assertTrue(delete Array.prototype[5]);
   }
 })();
+
+// Check slicing on arguments object.
+(function() {
+  function func(expected, a0, a1, a2) {
+    assertEquals(expected, Array.prototype.slice.call(arguments, 1));
+  }
+
+  func([]);
+  func(['a'], 'a');
+  func(['a', 1], 'a', 1);
+  func(['a', 1, undefined], 'a', 1, undefined);
+  func(['a', 1, undefined, void(0)], 'a', 1, undefined, void(0));
+})();
index a082abc..7060c5f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -360,3 +360,18 @@ function TestSpecialCasesInheritedElementSort() {
 }
 
 TestSpecialCasesInheritedElementSort();
+
+// Test that sort calls compare function with global object as receiver,
+// and with only elements of the array as arguments.
+function o(v) { 
+  return {__proto__: o.prototype, val: v};
+}
+var arr = [o(1), o(2), o(4), o(8), o(16), o(32), o(64), o(128), o(256), o(-0)];
+var global = this;
+function cmpTest(a, b) {
+  assertEquals(global, this);
+  assertTrue(a instanceof o);
+  assertTrue(b instanceof o);
+  return a.val - b.val;
+}
+arr.sort(cmpTest);
\ No newline at end of file
diff --git a/deps/v8/test/mjsunit/with-readonly.js b/deps/v8/test/mjsunit/with-readonly.js
new file mode 100644 (file)
index 0000000..e29520a
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that readonly variables are treated correctly.
+
+// Create an object with a read-only length property in the prototype
+// chain by putting the string split function in the prototype chain.
+var o = {};
+o.__proto__ = String.prototype.split;
+
+function f() {
+  with (o) {
+    length = 23;
+    length = 24;
+    assertEquals(24, length);
+  }
+}
+f();
+
index 91cbd6a..6af6611 100644 (file)
@@ -70,7 +70,8 @@
           'DEBUG',
           '_DEBUG',
           'ENABLE_DISASSEMBLER',
-          'V8_ENABLE_CHECKS'
+          'V8_ENABLE_CHECKS',
+          'OBJECT_PRINT',
         ],
         'msvs_settings': {
           'VCCLCompilerTool': {
index 51f1cfb..5254c6e 100644 (file)
                                        DEBUG,
                                        ENABLE_LOGGING_AND_PROFILING,
                                        V8_ENABLE_CHECKS,
+                                        OBJECT_PRINT,
                                        ENABLE_VMSTATE_TRACKING,
                                );
                                GCC_SYMBOLS_PRIVATE_EXTERN = YES;
                                        V8_TARGET_ARCH_IA32,
                                        DEBUG,
                                        V8_ENABLE_CHECKS,
+                                        OBJECT_PRINT,
                                        ENABLE_DEBUGGER_SUPPORT,
                                );
                                HEADER_SEARCH_PATHS = ../src;
                                        V8_TARGET_ARCH_IA32,
                                        DEBUG,
                                        V8_ENABLE_CHECKS,
+                                        OBJECT_PRINT,
                                        ENABLE_DEBUGGER_SUPPORT,
                                );
                                HEADER_SEARCH_PATHS = ../src;
index 5e3555a..60b79fe 100644 (file)
@@ -7,7 +7,7 @@
        <Tool
                Name="VCCLCompilerTool"
                Optimization="0"
-               PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS"
+               PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS,OBJECT_PRINT"
                RuntimeLibrary="1"
        />
        <Tool