diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index f1b47b06c3..c81d7a7376 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -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. diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct index 41c9faeb63..5908be1525 100644 --- a/deps/v8/SConstruct +++ b/deps/v8/SConstruct @@ -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', diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index 82de6b8b5e..2c0f35080d 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -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); }; diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index 5d7907251f..8ccc6f2d8b 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -231,7 +231,8 @@ SOURCES = { 'mode:release': [], 'mode:debug': [ 'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc' - ] + ], + 'objectprint:on': ['objects-debug.cc'] } diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index b85d658dc3..110468e231 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -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 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 func = + i::Handle(i::JSFunction::cast(object_func)); + + // Call ResetDateCache(0 but expect no exceptions: + bool caught_exception = false; + i::Handle result = + i::Execution::TryCall(func, i::Top::builtins(), 0, NULL, + &caught_exception); + } +} + + static i::Handle RegExpFlagsToString(RegExp::Flags flags) { char flags_buf[3]; int num_flags = 0; diff --git a/deps/v8/src/arm/code-stubs-arm.cc b/deps/v8/src/arm/code-stubs-arm.cc index 3670765a61..5ec8584f9e 100644 --- a/deps/v8/src/arm/code-stubs-arm.cc +++ b/deps/v8/src/arm/code-stubs-arm.cc @@ -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(¬_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); diff --git a/deps/v8/src/arm/lithium-arm.cc b/deps/v8/src/arm/lithium-arm.cc index 9c792316f5..e31d2e1d8a 100644 --- a/deps/v8/src/arm/lithium-arm.cc +++ b/deps/v8/src/arm/lithium-arm.cc @@ -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; diff --git a/deps/v8/src/arm/lithium-codegen-arm.cc b/deps/v8/src/arm/lithium-codegen-arm.cc index 533d32c747..dfc48917da 100644 --- a/deps/v8/src/arm/lithium-codegen-arm.cc +++ b/deps/v8/src/arm/lithium-codegen-arm.cc @@ -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(); } } diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 6effec1e31..4a13146590 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -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()); diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h index 3da8726777..97bbb2fb67 100644 --- a/deps/v8/src/arm/macro-assembler-arm.h +++ b/deps/v8/src/arm/macro-assembler-arm.h @@ -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 // --------------------------------------------------------------------------- diff --git a/deps/v8/src/array.js b/deps/v8/src/array.js index a805157b13..0f1e969f98 100644 --- a/deps/v8/src/array.js +++ b/deps/v8/src/array.js @@ -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; diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index 3b44efa9c0..eeb84128d7 100644 --- a/deps/v8/src/assembler.cc +++ b/deps/v8/src/assembler.cc @@ -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(data_)); + PrintF(out, " (%s)", reinterpret_cast(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 diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 72a9b15380..b68ad38970 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -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 diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index a833119e85..21381f15d5 100644 --- a/deps/v8/src/builtins.cc +++ b/deps/v8/src/builtins.cc @@ -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); diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index 8ba9971751..b7804b77f2 100644 --- a/deps/v8/src/code-stubs.h +++ b/deps/v8/src/code-stubs.h @@ -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) \ diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc index 8a64d77b70..da479e8fc1 100644 --- a/deps/v8/src/codegen.cc +++ b/deps/v8/src/codegen.cc @@ -215,8 +215,17 @@ void CodeGenerator::PrintCode(Handle 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 } diff --git a/deps/v8/src/counters.h b/deps/v8/src/counters.h index aed46cfb36..048fdaabf2 100644 --- a/deps/v8/src/counters.h +++ b/deps/v8/src/counters.h @@ -28,6 +28,9 @@ #ifndef V8_COUNTERS_H_ #define V8_COUNTERS_H_ +#include "../include/v8.h" +#include "allocation.h" + namespace v8 { namespace internal { diff --git a/deps/v8/src/date.js b/deps/v8/src/date.js index 38bb8eb254..bc70327c41 100644 --- a/deps/v8/src/date.js +++ b/deps/v8/src/date.js @@ -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() { diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 7709eb0e93..ca3c1db790 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -858,7 +858,7 @@ bool Debug::Load() { if (caught_exception) return false; // Debugger loaded. - debug_context_ = Handle::cast(GlobalHandles::Create(*context)); + debug_context_ = context; return true; } diff --git a/deps/v8/src/deoptimizer.cc b/deps/v8/src/deoptimizer.cc index 93839a49a8..dd70baaa16 100644 --- a/deps/v8/src/deoptimizer.cc +++ b/deps/v8/src/deoptimizer.cc @@ -1096,7 +1096,7 @@ int Translation::NumberOfOperandsFor(Opcode opcode) { } -#ifdef DEBUG +#ifdef OBJECT_PRINT const char* Translation::StringFor(Opcode opcode) { switch (opcode) { diff --git a/deps/v8/src/deoptimizer.h b/deps/v8/src/deoptimizer.h index 32edd1009f..2d7dfc895c 100644 --- a/deps/v8/src/deoptimizer.h +++ b/deps/v8/src/deoptimizer.h @@ -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 diff --git a/deps/v8/src/flag-definitions.h b/deps/v8/src/flag-definitions.h index facbec273b..f160a85afc 100644 --- a/deps/v8/src/flag-definitions.h +++ b/deps/v8/src/flag-definitions.h @@ -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") diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc index 96307a302d..58540f07bc 100644 --- a/deps/v8/src/full-codegen.cc +++ b/deps/v8/src/full-codegen.cc @@ -671,8 +671,12 @@ const FullCodeGenerator::InlineFunctionGenerator FullCodeGenerator::InlineFunctionGenerator FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) { - return kInlineFunctionGenerators[ - static_cast(id) - static_cast(Runtime::kFirstInlineFunction)]; + int lookup_index = + static_cast(id) - static_cast(Runtime::kFirstInlineFunction); + ASSERT(lookup_index >= 0); + ASSERT(static_cast(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); } diff --git a/deps/v8/src/heap-profiler.cc b/deps/v8/src/heap-profiler.cc index 002950031b..dfda7c6fec 100644 --- a/deps/v8/src/heap-profiler.cc +++ b/deps/v8/src/heap-profiler.cc @@ -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(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); diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index ccf9b47a35..1e9999164c 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -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 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; } diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index fbcc70df53..18a4afbe46 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -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]; diff --git a/deps/v8/src/hydrogen-instructions.cc b/deps/v8/src/hydrogen-instructions.cc index a96ee406ff..3f39888e9b 100644 --- a/deps/v8/src/hydrogen-instructions.cc +++ b/deps/v8/src/hydrogen-instructions.cc @@ -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()); } diff --git a/deps/v8/src/hydrogen-instructions.h b/deps/v8/src/hydrogen-instructions.h index aafa7a8830..cbbe8fcc88 100644 --- a/deps/v8/src/hydrogen-instructions.h +++ b/deps/v8/src/hydrogen-instructions.h @@ -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() 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: diff --git a/deps/v8/src/hydrogen.cc b/deps/v8/src/hydrogen.cc index 32108dc1cd..e34acd67d4 100644 --- a/deps/v8/src/hydrogen.cc +++ b/deps/v8/src/hydrogen.cc @@ -3165,6 +3165,9 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, if (lookup->type() == MAP_TRANSITION) { Handle 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 type, - LookupResult* lookup, - bool smi_and_map_check) { +HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, + Property* expr, + Handle 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; diff --git a/deps/v8/src/hydrogen.h b/deps/v8/src/hydrogen.h index 2c9aeac75c..ebabf3d292 100644 --- a/deps/v8/src/hydrogen.h +++ b/deps/v8/src/hydrogen.h @@ -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 type, - LookupResult* result, - bool smi_and_map_check); + HLoadNamedField* BuildLoadNamedField(HValue* object, + Property* expr, + Handle type, + LookupResult* result, + bool smi_and_map_check); HInstruction* BuildLoadNamedGeneric(HValue* object, Property* expr); HInstruction* BuildLoadKeyedFastElement(HValue* object, HValue* key, diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc index d75acab082..a371c96393 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.cc +++ b/deps/v8/src/ia32/code-stubs-ia32.cc @@ -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(&test_elem[0]); - char* elem2_start = reinterpret_cast(&test_elem[1]); - char* elem_in0 = reinterpret_cast(&(test_elem[0].in[0])); - char* elem_in1 = reinterpret_cast(&(test_elem[0].in[1])); - char* elem_out = reinterpret_cast(&(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 diff --git a/deps/v8/src/ia32/code-stubs-ia32.h b/deps/v8/src/ia32/code-stubs-ia32.h index 04f23ace9b..f66a8c7e45 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.h +++ b/deps/v8/src/ia32/code-stubs-ia32.h @@ -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); }; diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc index 4c9d05558b..2f14e82e14 100644 --- a/deps/v8/src/ia32/codegen-ia32.cc +++ b/deps/v8/src/ia32/codegen-ia32.cc @@ -7912,7 +7912,8 @@ void CodeGenerator::GenerateMathPow(ZoneList* args) { void CodeGenerator::GenerateMathSin(ZoneList* 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* args) { void CodeGenerator::GenerateMathCos(ZoneList* 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* args) { void CodeGenerator::GenerateMathLog(ZoneList* 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); } diff --git a/deps/v8/src/ia32/full-codegen-ia32.cc b/deps/v8/src/ia32/full-codegen-ia32.cc index be059cdfe3..13a11777ab 100644 --- a/deps/v8/src/ia32/full-codegen-ia32.cc +++ b/deps/v8/src/ia32/full-codegen-ia32.cc @@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitStringCompare(ZoneList* args) { void FullCodeGenerator::EmitMathSin(ZoneList* 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* args) { void FullCodeGenerator::EmitMathCos(ZoneList* 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* args) { void FullCodeGenerator::EmitMathLog(ZoneList* 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); diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.cc b/deps/v8/src/ia32/lithium-codegen-ia32.cc index 0e9773748e..d64f528e71 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.cc +++ b/deps/v8/src/ia32/lithium-codegen-ia32.cc @@ -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; diff --git a/deps/v8/src/ia32/lithium-codegen-ia32.h b/deps/v8/src/ia32/lithium-codegen-ia32.h index 5ac7b1edb2..6d8173a1cf 100644 --- a/deps/v8/src/ia32/lithium-codegen-ia32.h +++ b/deps/v8/src/ia32/lithium-codegen-ia32.h @@ -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); diff --git a/deps/v8/src/ia32/lithium-ia32.cc b/deps/v8/src/ia32/lithium-ia32.cc index e1148fc186..3b272d0b02 100644 --- a/deps/v8/src/ia32/lithium-ia32.cc +++ b/deps/v8/src/ia32/lithium-ia32.cc @@ -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); diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc index cb7b35ec43..53296d9272 100644 --- a/deps/v8/src/objects-debug.cc +++ b/deps/v8/src/objects-debug.cc @@ -35,32 +35,34 @@ 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(this), id); +#ifdef OBJECT_PRINT +void HeapObject::PrintHeader(FILE* out, const char* id) { + PrintF(out, "%p: [%s]\n", reinterpret_cast(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(p->get(i))); + PrintF(out, " %d: %d\n", i, static_cast(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(p->get(i))); + PrintF(out, " %d: %d\n", i, static_cast(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(p->get(i))); + PrintF(out, " %d: %d\n", i, static_cast(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(p->get(i))); + PrintF(out, " %d: %d\n", i, static_cast(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(p->get(i))); + PrintF(out, " %d: %d\n", i, static_cast(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(p->get(i))); + PrintF(out, " %d: %d\n", i, static_cast(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(this)); - PrintF(" - map = %p\n", reinterpret_cast(map())); - PrintF(" - prototype = %p\n", reinterpret_cast(GetPrototype())); - PrintF(" {\n"); - PrintProperties(); - PrintElements(); - PrintF(" }\n"); +void JSObject::JSObjectPrint(FILE* out) { + PrintF(out, "%p: [JSObject]\n", reinterpret_cast(this)); + PrintF(out, " - map = %p\n", reinterpret_cast(map())); + PrintF(out, " - prototype = %p\n", reinterpret_cast(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[] = "..."; + 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(map())); - PrintF(" - initial_map = "); +#ifdef OBJECT_PRINT +void JSFunction::JSFunctionPrint(FILE* out) { + HeapObject::PrintHeader(out, "Function"); + PrintF(out, " - map = 0x%p\n", reinterpret_cast(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(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; diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 96f5c4b247..ab2f964470 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -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(value())); +void Failure::FailurePrint(FILE* out) { + PrintF(out, "Failure(%p)", reinterpret_cast(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 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(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(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(" "); + PrintF(out, " "); } - 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(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 -void Dictionary::Print() { +void Dictionary::Print(FILE* out) { int capacity = HashTable::Capacity(); for (int i = 0; i < capacity; i++) { Object* k = HashTable::KeyAt(i); if (HashTable::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"); } } } diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 498ee451bc..c5fda7d038 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -607,10 +607,18 @@ class MaybeObject BASE_EMBEDDED { return reinterpret_cast(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 { // 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 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 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 diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 94ad57c9c2..08f77b8f30 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -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(); } diff --git a/deps/v8/src/platform-nullos.cc b/deps/v8/src/platform-nullos.cc index f34483dbc4..72ea0e5767 100644 --- a/deps/v8/src/platform-nullos.cc +++ b/deps/v8/src/platform-nullos.cc @@ -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. diff --git a/deps/v8/src/platform-posix.cc b/deps/v8/src/platform-posix.cc index c50d396ad3..ab5c0a3768 100644 --- a/deps/v8/src/platform-posix.cc +++ b/deps/v8/src/platform-posix.cc @@ -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 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(); } diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc index badc31beb3..4438045eaf 100644 --- a/deps/v8/src/platform-win32.cc +++ b/deps/v8/src/platform-win32.cc @@ -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 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; diff --git a/deps/v8/src/platform.h b/deps/v8/src/platform.h index 690f83c7fb..bdfbbab698 100644 --- a/deps/v8/src/platform.h +++ b/deps/v8/src/platform.h @@ -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. diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc index 364f51d4f1..34d18771cf 100644 --- a/deps/v8/src/profile-generator.cc +++ b/deps/v8/src/profile-generator.cc @@ -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()) { diff --git a/deps/v8/src/property.cc b/deps/v8/src/property.cc index b579b687b6..96774333e8 100644 --- a/deps/v8/src/property.cc +++ b/deps/v8/src/property.cc @@ -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()); } diff --git a/deps/v8/src/property.h b/deps/v8/src/property.h index 537b4e6e26..c39fe41e75 100644 --- a/deps/v8/src/property.h +++ b/deps/v8/src/property.h @@ -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() { diff --git a/deps/v8/src/regexp.js b/deps/v8/src/regexp.js index dd27266a94..0de66c644e 100644 --- a/deps/v8/src/regexp.js +++ b/deps/v8/src/regexp.js @@ -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. diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 0fd2f8b4bf..724a436348 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -7204,7 +7204,7 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) { // extension object itself. if ((attributes & READ_ONLY) == 0 || (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { - Handle set = SetProperty(context_ext, name, value, attributes); + Handle 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 diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 8e9d889607..fca1032969 100644 --- a/deps/v8/src/spaces.cc +++ b/deps/v8/src/spaces.cc @@ -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(array[i]); + uintptr_t* subarray = reinterpret_cast(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(chunk_start)) { + if (fine_grained[index] != chunk_start) { index++; - ASSERT(fine_grained[index] == static_cast(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(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(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(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(table[index]); + uintptr_t* more_fine_grained_table = + reinterpret_cast(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(more_fine_grained_table)); + table[index] = reinterpret_cast(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]; // ----------------------------------------------------------------------------- diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h index 2c17ef0088..4f2d07b0c8 100644 --- a/deps/v8/src/spaces.h +++ b/deps/v8/src/spaces.h @@ -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)); diff --git a/deps/v8/src/string-stream.cc b/deps/v8/src/string-stream.cc index d1859a20fa..7abd1bbe85 100644 --- a/deps/v8/src/string-stream.cc +++ b/deps/v8/src/string-stream.cc @@ -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]); } diff --git a/deps/v8/src/string-stream.h b/deps/v8/src/string-stream.h index b74c793958..b3f2e0d76e 100644 --- a/deps/v8/src/string-stream.h +++ b/deps/v8/src/string-stream.h @@ -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 ToString(); SmartPointer ToCString() const; diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js index 6d4e0c18f7..95275995e1 100644 --- a/deps/v8/src/string.js +++ b/deps/v8/src/string.js @@ -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); } } diff --git a/deps/v8/src/utils.cc b/deps/v8/src/utils.cc index 2c234bb762..d0ec4ef528 100644 --- a/deps/v8/src/utils.cc +++ b/deps/v8/src/utils.cc @@ -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); } diff --git a/deps/v8/src/v8-counters.h b/deps/v8/src/v8-counters.h index a5cf42e905..fa5d581eab 100644 --- a/deps/v8/src/v8-counters.h +++ b/deps/v8/src/v8-counters.h @@ -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 { diff --git a/deps/v8/src/v8utils.h b/deps/v8/src/v8utils.h index 59b3898bda..b000d14409 100644 --- a/deps/v8/src/v8utils.h +++ b/deps/v8/src/v8utils.h @@ -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 diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 60e61b1164..d2c0960508 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -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 diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc index 6c8b333984..9a25572298 100644 --- a/deps/v8/src/x64/codegen-x64.cc +++ b/deps/v8/src/x64/codegen-x64.cc @@ -6784,9 +6784,9 @@ void CodeGenerator::GenerateSwapElements(ZoneList* 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. diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index aa5fe59bd9..a23ee171f2 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/deps/v8/test/cctest/test-heap.cc @@ -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 a(Top::context()->global()->GetProperty( + *Factory::LookupAsciiSymbol("a"))->ToObjectChecked()); + v8::Handle 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()); + } +} diff --git a/deps/v8/test/mjsunit/array-slice.js b/deps/v8/test/mjsunit/array-slice.js index 8f9ce53586..50b5b27306 100644 --- a/deps/v8/test/mjsunit/array-slice.js +++ b/deps/v8/test/mjsunit/array-slice.js @@ -218,3 +218,16 @@ 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)); +})(); diff --git a/deps/v8/test/mjsunit/array-sort.js b/deps/v8/test/mjsunit/array-sort.js index a082abcb17..7060c5f366 100644 --- a/deps/v8/test/mjsunit/array-sort.js +++ b/deps/v8/test/mjsunit/array-sort.js @@ -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 index 0000000000..e29520a4dc --- /dev/null +++ b/deps/v8/test/mjsunit/with-readonly.js @@ -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(); + diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp index 91cbd6ab3b..6af6611d1b 100644 --- a/deps/v8/tools/gyp/v8.gyp +++ b/deps/v8/tools/gyp/v8.gyp @@ -70,7 +70,8 @@ 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER', - 'V8_ENABLE_CHECKS' + 'V8_ENABLE_CHECKS', + 'OBJECT_PRINT', ], 'msvs_settings': { 'VCCLCompilerTool': { diff --git a/deps/v8/tools/v8.xcodeproj/project.pbxproj b/deps/v8/tools/v8.xcodeproj/project.pbxproj index 51f1cfbf07..5254c6e665 100644 --- a/deps/v8/tools/v8.xcodeproj/project.pbxproj +++ b/deps/v8/tools/v8.xcodeproj/project.pbxproj @@ -1850,6 +1850,7 @@ DEBUG, ENABLE_LOGGING_AND_PROFILING, V8_ENABLE_CHECKS, + OBJECT_PRINT, ENABLE_VMSTATE_TRACKING, ); GCC_SYMBOLS_PRIVATE_EXTERN = YES; @@ -1914,6 +1915,7 @@ V8_TARGET_ARCH_IA32, DEBUG, V8_ENABLE_CHECKS, + OBJECT_PRINT, ENABLE_DEBUGGER_SUPPORT, ); HEADER_SEARCH_PATHS = ../src; @@ -1976,6 +1978,7 @@ V8_TARGET_ARCH_IA32, DEBUG, V8_ENABLE_CHECKS, + OBJECT_PRINT, ENABLE_DEBUGGER_SUPPORT, ); HEADER_SEARCH_PATHS = ../src; diff --git a/deps/v8/tools/visual_studio/debug.vsprops b/deps/v8/tools/visual_studio/debug.vsprops index 5e3555a9d7..60b79fe07c 100644 --- a/deps/v8/tools/visual_studio/debug.vsprops +++ b/deps/v8/tools/visual_studio/debug.vsprops @@ -7,7 +7,7 @@