Browse Source

Upgrade V8 to 3.0.4

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
1a894b39b3
  1. 11
      deps/v8/ChangeLog
  2. 13
      deps/v8/SConstruct
  3. 15
      deps/v8/include/v8.h
  4. 3
      deps/v8/src/SConscript
  5. 29
      deps/v8/src/api.cc
  6. 105
      deps/v8/src/arm/code-stubs-arm.cc
  7. 9
      deps/v8/src/arm/lithium-arm.cc
  8. 15
      deps/v8/src/arm/lithium-codegen-arm.cc
  9. 38
      deps/v8/src/arm/macro-assembler-arm.cc
  10. 13
      deps/v8/src/arm/macro-assembler-arm.h
  11. 67
      deps/v8/src/array.js
  12. 23
      deps/v8/src/assembler.cc
  13. 2
      deps/v8/src/assembler.h
  14. 53
      deps/v8/src/builtins.cc
  15. 3
      deps/v8/src/code-stubs.h
  16. 11
      deps/v8/src/codegen.cc
  17. 3
      deps/v8/src/counters.h
  18. 33
      deps/v8/src/date.js
  19. 2
      deps/v8/src/debug.cc
  20. 2
      deps/v8/src/deoptimizer.cc
  21. 2
      deps/v8/src/deoptimizer.h
  22. 5
      deps/v8/src/flag-definitions.h
  23. 9
      deps/v8/src/full-codegen.cc
  24. 4
      deps/v8/src/heap-profiler.cc
  25. 95
      deps/v8/src/heap.cc
  26. 16
      deps/v8/src/heap.h
  27. 7
      deps/v8/src/hydrogen-instructions.cc
  28. 6
      deps/v8/src/hydrogen-instructions.h
  29. 12
      deps/v8/src/hydrogen.cc
  30. 2
      deps/v8/src/hydrogen.h
  31. 232
      deps/v8/src/ia32/code-stubs-ia32.cc
  32. 29
      deps/v8/src/ia32/code-stubs-ia32.h
  33. 9
      deps/v8/src/ia32/codegen-ia32.cc
  34. 9
      deps/v8/src/ia32/full-codegen-ia32.cc
  35. 28
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  36. 2
      deps/v8/src/ia32/lithium-codegen-ia32.h
  37. 2
      deps/v8/src/ia32/lithium-ia32.cc
  38. 826
      deps/v8/src/objects-debug.cc
  39. 131
      deps/v8/src/objects.cc
  40. 343
      deps/v8/src/objects.h
  41. 4
      deps/v8/src/parser.cc
  42. 13
      deps/v8/src/platform-nullos.cc
  43. 27
      deps/v8/src/platform-posix.cc
  44. 14
      deps/v8/src/platform-win32.cc
  45. 4
      deps/v8/src/platform.h
  46. 8
      deps/v8/src/profile-generator.cc
  47. 62
      deps/v8/src/property.cc
  48. 8
      deps/v8/src/property.h
  49. 27
      deps/v8/src/regexp.js
  50. 2
      deps/v8/src/runtime.cc
  51. 53
      deps/v8/src/spaces.cc
  52. 9
      deps/v8/src/spaces.h
  53. 6
      deps/v8/src/string-stream.cc
  54. 3
      deps/v8/src/string-stream.h
  55. 67
      deps/v8/src/string.js
  56. 12
      deps/v8/src/utils.cc
  57. 2
      deps/v8/src/v8-counters.h
  58. 10
      deps/v8/src/v8utils.h
  59. 4
      deps/v8/src/version.cc
  60. 4
      deps/v8/src/x64/codegen-x64.cc
  61. 64
      deps/v8/test/cctest/test-heap.cc
  62. 13
      deps/v8/test/mjsunit/array-slice.js
  63. 17
      deps/v8/test/mjsunit/array-sort.js
  64. 43
      deps/v8/test/mjsunit/with-readonly.js
  65. 3
      deps/v8/tools/gyp/v8.gyp
  66. 3
      deps/v8/tools/v8.xcodeproj/project.pbxproj
  67. 2
      deps/v8/tools/visual_studio/debug.vsprops

11
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 2010-12-17: Version 3.0.3
Reapplied all changes for version 3.0.1. Reapplied all changes for version 3.0.1.

13
deps/v8/SConstruct

@ -108,11 +108,14 @@ LIBRARY_FLAGS = {
'CPPDEFINES': ['V8_INTERPRETED_REGEXP'] 'CPPDEFINES': ['V8_INTERPRETED_REGEXP']
}, },
'mode:debug': { 'mode:debug': {
'CPPDEFINES': ['V8_ENABLE_CHECKS'] 'CPPDEFINES': ['V8_ENABLE_CHECKS', 'OBJECT_PRINT']
}, },
'vmstate:on': { 'vmstate:on': {
'CPPDEFINES': ['ENABLE_VMSTATE_TRACKING'], 'CPPDEFINES': ['ENABLE_VMSTATE_TRACKING'],
}, },
'objectprint:on': {
'CPPDEFINES': ['OBJECT_PRINT'],
},
'protectheap:on': { 'protectheap:on': {
'CPPDEFINES': ['ENABLE_VMSTATE_TRACKING', 'ENABLE_HEAP_PROTECTION'], 'CPPDEFINES': ['ENABLE_VMSTATE_TRACKING', 'ENABLE_HEAP_PROTECTION'],
}, },
@ -225,8 +228,7 @@ LIBRARY_FLAGS = {
'LINKFLAGS': ['-m64'], 'LINKFLAGS': ['-m64'],
}, },
'prof:oprofile': { 'prof:oprofile': {
'CPPDEFINES': ['ENABLE_OPROFILE_AGENT'], 'CPPDEFINES': ['ENABLE_OPROFILE_AGENT']
'LIBS': ['opagent', 'bfd']
} }
}, },
'msvc': { 'msvc': {
@ -711,6 +713,11 @@ SIMPLE_OPTIONS = {
'default': 'off', 'default': 'off',
'help': 'enable VM state tracking' 'help': 'enable VM state tracking'
}, },
'objectprint': {
'values': ['on', 'off'],
'default': 'off',
'help': 'enable object printing'
},
'protectheap': { 'protectheap': {
'values': ['on', 'off'], 'values': ['on', 'off'],
'default': 'off', 'default': 'off',

15
deps/v8/include/v8.h

@ -1355,6 +1355,21 @@ class Date : public Value {
V8EXPORT double NumberValue() const; V8EXPORT double NumberValue() const;
static inline Date* Cast(v8::Value* obj); 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: private:
V8EXPORT static void CheckCast(v8::Value* obj); V8EXPORT static void CheckCast(v8::Value* obj);
}; };

3
deps/v8/src/SConscript

@ -231,7 +231,8 @@ SOURCES = {
'mode:release': [], 'mode:release': [],
'mode:debug': [ 'mode:debug': [
'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc' 'objects-debug.cc', 'prettyprinter.cc', 'regexp-macro-assembler-tracer.cc'
] ],
'objectprint:on': ['objects-debug.cc']
} }

29
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<i::String> func_name_str =
i::Factory::LookupAsciiSymbol("ResetDateCache");
i::MaybeObject* result = i::Top::builtins()->GetProperty(*func_name_str);
i::Object* object_func;
if (!result->ToObject(&object_func)) {
return;
}
if (object_func->IsJSFunction()) {
i::Handle<i::JSFunction> func =
i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
// Call ResetDateCache(0 but expect no exceptions:
bool caught_exception = false;
i::Handle<i::Object> result =
i::Execution::TryCall(func, i::Top::builtins(), 0, NULL,
&caught_exception);
}
}
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) { static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
char flags_buf[3]; char flags_buf[3];
int num_flags = 0; int num_flags = 0;

105
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 // Uses registers r0 to r4. Expected input is
// necessary. Uses r1 for the object, r0 for the function that it may // function in r0 (or at sp+1*ptrsz) and object in
// be an instance of (these are fetched from the stack). // r1 (or at sp), depending on whether or not
// args_in_registers() is true.
void InstanceofStub::Generate(MacroAssembler* masm) { void InstanceofStub::Generate(MacroAssembler* masm) {
// Get the object - slow case for smis (we may need to throw an exception // Fixed register usage throughout the stub:
// depending on the rhs). const Register object = r1; // Object (lhs).
Label slow, loop, is_instance, is_not_instance; const Register map = r3; // Map of the object.
__ ldr(r0, MemOperand(sp, 1 * kPointerSize)); const Register function = r0; // Function (rhs).
__ BranchOnSmi(r0, &slow); const Register prototype = r4; // Prototype of the function.
const Register scratch = r2;
// Check that the left hand is a JS object and put map in r3. Label slow, loop, is_instance, is_not_instance, not_js_object;
__ CompareObjectType(r0, r3, r2, FIRST_JS_OBJECT_TYPE); if (!args_in_registers()) {
__ b(lt, &slow); __ ldr(function, MemOperand(sp, 1 * kPointerSize));
__ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); __ ldr(object, MemOperand(sp, 0));
__ b(gt, &slow); }
// Get the prototype of the function (r4 is result, r2 is scratch). // Check that the left hand is a JS object and load map.
__ ldr(r1, MemOperand(sp, 0)); __ BranchOnSmi(object, &slow);
// r1 is function, r3 is map. __ IsObjectJSObjectType(object, map, scratch, &slow);
// Look up the function and the map in the instanceof cache. // Look up the function and the map in the instanceof cache.
Label miss; Label miss;
__ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex); __ LoadRoot(ip, Heap::kInstanceofCacheFunctionRootIndex);
__ cmp(r1, ip); __ cmp(object, ip);
__ b(ne, &miss); __ b(ne, &miss);
__ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex); __ LoadRoot(ip, Heap::kInstanceofCacheMapRootIndex);
__ cmp(r3, ip); __ cmp(map, ip);
__ b(ne, &miss); __ b(ne, &miss);
__ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); __ LoadRoot(function, Heap::kInstanceofCacheAnswerRootIndex);
__ pop(); __ Ret(args_in_registers() ? 0 : 2);
__ pop();
__ mov(pc, Operand(lr));
__ bind(&miss); __ bind(&miss);
__ TryGetFunctionPrototype(r1, r4, r2, &slow); __ TryGetFunctionPrototype(object, prototype, scratch, &slow);
// Check that the function prototype is a JS object. // Check that the function prototype is a JS object.
__ BranchOnSmi(r4, &slow); __ BranchOnSmi(prototype, &slow);
__ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE); __ IsObjectJSObjectType(prototype, scratch, scratch, &slow);
__ b(lt, &slow);
__ cmp(r5, Operand(LAST_JS_OBJECT_TYPE));
__ b(gt, &slow);
__ StoreRoot(r1, Heap::kInstanceofCacheFunctionRootIndex); __ StoreRoot(object, Heap::kInstanceofCacheFunctionRootIndex);
__ StoreRoot(r3, Heap::kInstanceofCacheMapRootIndex); __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex);
// Register mapping: r3 is object map and r4 is function prototype. // Register mapping: r3 is object map and r4 is function prototype.
// Get prototype of object into r2. // 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. // Loop through the prototype chain looking for the function prototype.
__ bind(&loop); __ bind(&loop);
__ cmp(r2, Operand(r4)); __ cmp(scratch, Operand(prototype));
__ b(eq, &is_instance); __ b(eq, &is_instance);
__ LoadRoot(ip, Heap::kNullValueRootIndex); __ LoadRoot(ip, Heap::kNullValueRootIndex);
__ cmp(r2, ip); __ cmp(scratch, ip);
__ b(eq, &is_not_instance); __ b(eq, &is_not_instance);
__ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset));
__ ldr(r2, FieldMemOperand(r2, Map::kPrototypeOffset)); __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset));
__ jmp(&loop); __ jmp(&loop);
__ bind(&is_instance); __ bind(&is_instance);
__ mov(r0, Operand(Smi::FromInt(0))); __ mov(r0, Operand(Smi::FromInt(0)));
__ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex);
__ pop(); __ Ret(args_in_registers() ? 0 : 2);
__ pop();
__ mov(pc, Operand(lr)); // Return.
__ bind(&is_not_instance); __ bind(&is_not_instance);
__ mov(r0, Operand(Smi::FromInt(1))); __ mov(r0, Operand(Smi::FromInt(1)));
__ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); __ Ret(args_in_registers() ? 0 : 2);
__ pop();
__ pop(); Label object_not_null, object_not_null_or_smi;
__ mov(pc, Operand(lr)); // Return. __ bind(&not_js_object);
// Before null, smi and string value checks, check that the rhs is a function
// as for a non-function rhs an exception needs to be thrown.
__ BranchOnSmi(function, &slow);
__ CompareObjectType(function, map, scratch, JS_FUNCTION_TYPE);
__ b(ne, &slow);
// Null is not instance of anything.
__ cmp(scratch, Operand(Factory::null_value()));
__ b(ne, &object_not_null);
__ mov(r0, Operand(Smi::FromInt(1)));
__ Ret(args_in_registers() ? 0 : 2);
__ bind(&object_not_null);
// Smi values are not instances of anything.
__ BranchOnNotSmi(object, &object_not_null_or_smi);
__ mov(r0, Operand(Smi::FromInt(1)));
__ Ret(args_in_registers() ? 0 : 2);
__ bind(&object_not_null_or_smi);
// String values are not instances of anything.
__ IsObjectJSStringType(object, scratch, &slow);
__ mov(r0, Operand(Smi::FromInt(1)));
__ Ret(args_in_registers() ? 0 : 2);
// Slow-case. Tail call builtin. // Slow-case. Tail call builtin.
__ bind(&slow); __ bind(&slow);

9
deps/v8/src/arm/lithium-arm.cc

@ -1316,7 +1316,8 @@ LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) {
LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) {
LInstruction* result = 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); return MarkAsCall(DefineFixed(result, r0), instr);
} }
@ -1375,6 +1376,12 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
case kMathLog: case kMathLog:
Abort("MathLog LUnaryMathOperation not implemented"); Abort("MathLog LUnaryMathOperation not implemented");
return NULL; return NULL;
case kMathCos:
Abort("MathCos LUnaryMathOperation not implemented");
return NULL;
case kMathSin:
Abort("MathSin LUnaryMathOperation not implemented");
return NULL;
default: default:
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;

15
deps/v8/src/arm/lithium-codegen-arm.cc

@ -1337,7 +1337,14 @@ void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) {
void LCodeGen::DoInstanceOf(LInstanceOf* 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) { 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) { void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
ASSERT(instr->op() == kMathFloor ||
instr->op() == kMathAbs);
switch (instr->op()) { switch (instr->op()) {
case kMathAbs: case kMathAbs:
DoMathAbs(instr); DoMathAbs(instr);
@ -1576,6 +1580,7 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
DoMathSqrt(instr); DoMathSqrt(instr);
break; break;
default: default:
Abort("Unimplemented type of LUnaryMathOperation.");
UNREACHABLE(); UNREACHABLE();
} }
} }

38
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, void MacroAssembler::Swap(Register reg1,
Register reg2, Register reg2,
Register scratch, 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 #ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::DebugBreak() { void MacroAssembler::DebugBreak() {
ASSERT(allow_stub_calls()); ASSERT(allow_stub_calls());

13
deps/v8/src/arm/macro-assembler-arm.h

@ -96,6 +96,7 @@ class MacroAssembler: public Assembler {
// from the stack, clobbering only the sp register. // from the stack, clobbering only the sp register.
void Drop(int count, Condition cond = al); 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 // Swap two registers. If the scratch register is omitted then a slightly
// less efficient form using xor instead of mov is emitted. // less efficient form using xor instead of mov is emitted.
@ -298,6 +299,18 @@ class MacroAssembler: public Assembler {
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag); 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 #ifdef ENABLE_DEBUGGER_SUPPORT
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

67
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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -677,39 +677,76 @@ function ArraySort(comparefn) {
function QuickSort(a, from, to) { function QuickSort(a, from, to) {
// Insertion sort is faster for short arrays. // Insertion sort is faster for short arrays.
if (to - from <= 22) { if (to - from <= 10) {
InsertionSort(a, from, to); InsertionSort(a, from, to);
return; return;
} }
var pivot_index = $floor($random() * (to - from)) + from; // Find a pivot as the median of first, last and middle element.
var pivot = a[pivot_index]; var v0 = a[from];
// Issue 95: Keep the pivot element out of the comparisons to avoid var v1 = a[to - 1];
// infinite recursion if comparefn(pivot, pivot) != 0. var middle_index = from + ((to - from) >> 1);
%_SwapElements(a, from, pivot_index); var v2 = a[middle_index];
var low_end = from; // Upper bound of the elements lower than pivot. var c01 = %_CallFunction(global_receiver, v0, v1, comparefn);
var high_start = to; // Lower bound of the elements greater than pivot. 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 low_end to i are elements equal to pivot.
// From i to high_start are elements that haven't been compared yet. // 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 element = a[i];
var order = %_CallFunction(global_receiver, element, pivot, comparefn); var order = %_CallFunction(global_receiver, element, pivot, comparefn);
if (order < 0) { if (order < 0) {
%_SwapElements(a, i, low_end); %_SwapElements(a, i, low_end);
i++;
low_end++; low_end++;
} else if (order > 0) { } else if (order > 0) {
do {
high_start--; 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); %_SwapElements(a, i, high_start);
} else { // order == 0 if (order < 0) {
i++; %_SwapElements(a, i, low_end);
low_end++;
}
} }
} }
QuickSort(a, from, low_end); QuickSort(a, from, low_end);
QuickSort(a, high_start, to); QuickSort(a, high_start, to);
} }
// Copies elements in the range 0..length from obj's prototype chain // Copy 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 // to obj itself, if obj has holes. Return one more than the maximal index
// of a prototype property. // of a prototype property.
function CopyFromPrototype(obj, length) { function CopyFromPrototype(obj, length) {
var max = 0; var max = 0;

23
deps/v8/src/assembler.cc

@ -467,34 +467,35 @@ const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
} }
void RelocInfo::Print() { void RelocInfo::Print(FILE* out) {
PrintF("%p %s", pc_, RelocModeName(rmode_)); PrintF(out, "%p %s", pc_, RelocModeName(rmode_));
if (IsComment(rmode_)) { if (IsComment(rmode_)) {
PrintF(" (%s)", reinterpret_cast<char*>(data_)); PrintF(out, " (%s)", reinterpret_cast<char*>(data_));
} else if (rmode_ == EMBEDDED_OBJECT) { } else if (rmode_ == EMBEDDED_OBJECT) {
PrintF(" ("); PrintF(out, " (");
target_object()->ShortPrint(); target_object()->ShortPrint(out);
PrintF(")"); PrintF(out, ")");
} else if (rmode_ == EXTERNAL_REFERENCE) { } else if (rmode_ == EXTERNAL_REFERENCE) {
ExternalReferenceEncoder ref_encoder; ExternalReferenceEncoder ref_encoder;
PrintF(" (%s) (%p)", PrintF(out, " (%s) (%p)",
ref_encoder.NameOfAddress(*target_reference_address()), ref_encoder.NameOfAddress(*target_reference_address()),
*target_reference_address()); *target_reference_address());
} else if (IsCodeTarget(rmode_)) { } else if (IsCodeTarget(rmode_)) {
Code* code = Code::GetCodeFromTargetAddress(target_address()); 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_)) { } else if (IsPosition(rmode_)) {
PrintF(" (%" V8_PTR_PREFIX "d)", data()); PrintF(out, " (%" V8_PTR_PREFIX "d)", data());
} else if (rmode_ == RelocInfo::RUNTIME_ENTRY) { } else if (rmode_ == RelocInfo::RUNTIME_ENTRY) {
// Depotimization bailouts are stored as runtime entries. // Depotimization bailouts are stored as runtime entries.
int id = Deoptimizer::GetDeoptimizationId( int id = Deoptimizer::GetDeoptimizationId(
target_address(), Deoptimizer::EAGER); target_address(), Deoptimizer::EAGER);
if (id != Deoptimizer::kNotDeoptimizationEntry) { if (id != Deoptimizer::kNotDeoptimizationEntry) {
PrintF(" (deoptimization bailout %d)", id); PrintF(out, " (deoptimization bailout %d)", id);
} }
} }
PrintF("\n"); PrintF(out, "\n");
} }
#endif // ENABLE_DISASSEMBLER #endif // ENABLE_DISASSEMBLER

2
deps/v8/src/assembler.h

@ -322,7 +322,7 @@ class RelocInfo BASE_EMBEDDED {
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
// Printing // Printing
static const char* RelocModeName(Mode rmode); static const char* RelocModeName(Mode rmode);
void Print(); void Print(FILE* out);
#endif // ENABLE_DISASSEMBLER #endif // ENABLE_DISASSEMBLER
#ifdef DEBUG #ifdef DEBUG
// Debugging // Debugging

53
deps/v8/src/builtins.cc

@ -515,10 +515,10 @@ BUILTIN(ArrayShift) {
Object* elms_obj; Object* elms_obj;
{ MaybeObject* maybe_elms_obj = { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver); EnsureJSArrayWithWritableFastElements(receiver);
if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
} }
if (elms_obj == NULL || if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArrayShift", args); return CallJsBuiltin("ArrayShift", args);
} }
FixedArray* elms = FixedArray::cast(elms_obj); FixedArray* elms = FixedArray::cast(elms_obj);
@ -557,10 +557,10 @@ BUILTIN(ArrayUnshift) {
Object* elms_obj; Object* elms_obj;
{ MaybeObject* maybe_elms_obj = { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver); EnsureJSArrayWithWritableFastElements(receiver);
if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
} }
if (elms_obj == NULL || if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArrayUnshift", args); return CallJsBuiltin("ArrayUnshift", args);
} }
FixedArray* elms = FixedArray::cast(elms_obj); FixedArray* elms = FixedArray::cast(elms_obj);
@ -611,21 +611,46 @@ BUILTIN(ArrayUnshift) {
BUILTIN(ArraySlice) { BUILTIN(ArraySlice) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj; FixedArray* elms;
int len = -1;
{ MaybeObject* maybe_elms_obj = { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver); EnsureJSArrayWithWritableFastElements(receiver);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; Object* elms_obj;
} if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) {
if (elms_obj == NULL || if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArraySlice", args); return CallJsBuiltin("ArraySlice", args);
} }
FixedArray* elms = FixedArray::cast(elms_obj); elms = FixedArray::cast(elms_obj);
JSArray* array = JSArray::cast(receiver); JSArray* array = JSArray::cast(receiver);
ASSERT(array->HasFastElements()); ASSERT(array->HasFastElements());
int len = Smi::cast(array->length())->value(); 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; int n_arguments = args.length() - 1;
// Note carefully choosen defaults---if argument is missing, // Note carefully choosen defaults---if argument is missing,
@ -693,10 +718,10 @@ BUILTIN(ArraySplice) {
Object* elms_obj; Object* elms_obj;
{ MaybeObject* maybe_elms_obj = { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver); EnsureJSArrayWithWritableFastElements(receiver);
if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
} }
if (elms_obj == NULL || if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArraySplice", args); return CallJsBuiltin("ArraySplice", args);
} }
FixedArray* elms = FixedArray::cast(elms_obj); FixedArray* elms = FixedArray::cast(elms_obj);

3
deps/v8/src/code-stubs.h

@ -47,7 +47,7 @@ namespace internal {
V(Compare) \ V(Compare) \
V(CompareIC) \ V(CompareIC) \
V(MathPow) \ V(MathPow) \
V(TranscendentalCacheSSE2) \ V(TranscendentalCache) \
V(RecordWrite) \ V(RecordWrite) \
V(ConvertToDouble) \ V(ConvertToDouble) \
V(WriteInt32ToHeapNumber) \ V(WriteInt32ToHeapNumber) \
@ -56,7 +56,6 @@ namespace internal {
V(FastNewClosure) \ V(FastNewClosure) \
V(FastNewContext) \ V(FastNewContext) \
V(FastCloneShallowArray) \ V(FastCloneShallowArray) \
V(TranscendentalCache) \
V(GenericUnaryOp) \ V(GenericUnaryOp) \
V(RevertToNumber) \ V(RevertToNumber) \
V(ToBoolean) \ V(ToBoolean) \

11
deps/v8/src/codegen.cc

@ -215,8 +215,17 @@ void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
} }
PrintF("\n\n"); PrintF("\n\n");
} }
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"); PrintF("--- Code ---\n");
code->Disassemble(*function->name()->ToCString()); }
code->Disassemble(*function->debug_name()->ToCString());
} }
#endif // ENABLE_DISASSEMBLER #endif // ENABLE_DISASSEMBLER
} }

3
deps/v8/src/counters.h

@ -28,6 +28,9 @@
#ifndef V8_COUNTERS_H_ #ifndef V8_COUNTERS_H_
#define V8_COUNTERS_H_ #define V8_COUNTERS_H_
#include "../include/v8.h"
#include "allocation.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

33
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() { function SetupDate() {

2
deps/v8/src/debug.cc

@ -858,7 +858,7 @@ bool Debug::Load() {
if (caught_exception) return false; if (caught_exception) return false;
// Debugger loaded. // Debugger loaded.
debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context)); debug_context_ = context;
return true; return true;
} }

2
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) { const char* Translation::StringFor(Opcode opcode) {
switch (opcode) { switch (opcode) {

2
deps/v8/src/deoptimizer.h

@ -476,7 +476,7 @@ class Translation BASE_EMBEDDED {
static int NumberOfOperandsFor(Opcode opcode); static int NumberOfOperandsFor(Opcode opcode);
#ifdef DEBUG #ifdef OBJECT_PRINT
static const char* StringFor(Opcode opcode); static const char* StringFor(Opcode opcode);
#endif #endif

5
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(h, false, "print this message")
DEFINE_bool(new_snapshot, true, "use new snapshot implementation") DEFINE_bool(new_snapshot, true, "use new snapshot implementation")
// objects.cc
DEFINE_bool(use_verbose_printer, true, "allows verbose printing")
// parser.cc // parser.cc
DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") 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 // codegen-ia32.cc / codegen-arm.cc
DEFINE_bool(print_code, false, "print generated code") DEFINE_bool(print_code, false, "print generated code")
DEFINE_bool(print_opt_code, false, "print optimized 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_code_verbose, false, "print more information for code")
DEFINE_bool(print_builtin_code, false, "print generated code for builtins") DEFINE_bool(print_builtin_code, false, "print generated code for builtins")

9
deps/v8/src/full-codegen.cc

@ -671,8 +671,12 @@ const FullCodeGenerator::InlineFunctionGenerator
FullCodeGenerator::InlineFunctionGenerator FullCodeGenerator::InlineFunctionGenerator
FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) { FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) {
return kInlineFunctionGenerators[ int lookup_index =
static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)]; static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction);
ASSERT(lookup_index >= 0);
ASSERT(static_cast<size_t>(lookup_index) <
ARRAY_SIZE(kInlineFunctionGenerators));
return kInlineFunctionGenerators[lookup_index];
} }
@ -684,7 +688,6 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
ASSERT(function->intrinsic_type == Runtime::INLINE); ASSERT(function->intrinsic_type == Runtime::INLINE);
InlineFunctionGenerator generator = InlineFunctionGenerator generator =
FindInlineFunctionGenerator(function->function_id); FindInlineFunctionGenerator(function->function_id);
ASSERT(generator != NULL);
((*this).*(generator))(args); ((*this).*(generator))(args);
} }

4
deps/v8/src/heap-profiler.cc

@ -367,7 +367,6 @@ HeapSnapshot* HeapProfiler::TakeSnapshot(String* name,
HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name, HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
int type, int type,
v8::ActivityControl* control) { v8::ActivityControl* control) {
Heap::CollectAllGarbage(true);
HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type); HeapSnapshot::Type s_type = static_cast<HeapSnapshot::Type>(type);
HeapSnapshot* result = HeapSnapshot* result =
snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++); snapshots_->NewSnapshot(s_type, name, next_snapshot_uid_++);
@ -379,6 +378,7 @@ HeapSnapshot* HeapProfiler::TakeSnapshotImpl(const char* name,
break; break;
} }
case HeapSnapshot::kAggregated: { case HeapSnapshot::kAggregated: {
Heap::CollectAllGarbage(true);
AggregatedHeapSnapshot agg_snapshot; AggregatedHeapSnapshot agg_snapshot;
AggregatedHeapSnapshotGenerator generator(&agg_snapshot); AggregatedHeapSnapshotGenerator generator(&agg_snapshot);
generator.GenerateSnapshot(); generator.GenerateSnapshot();
@ -808,7 +808,7 @@ void AggregatedHeapSnapshotGenerator::CollectStats(HeapObject* obj) {
void AggregatedHeapSnapshotGenerator::GenerateSnapshot() { void AggregatedHeapSnapshotGenerator::GenerateSnapshot() {
HeapIterator iterator(HeapIterator::kPreciseFiltering); HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
CollectStats(obj); CollectStats(obj);
agg_snapshot_->js_cons_profile()->CollectStats(obj); agg_snapshot_->js_cons_profile()->CollectStats(obj);

95
deps/v8/src/heap.cc

@ -4483,7 +4483,7 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
MemoryAllocator::Size() + MemoryAllocator::Available(); MemoryAllocator::Size() + MemoryAllocator::Available();
*stats->os_error = OS::GetLastError(); *stats->os_error = OS::GetLastError();
if (take_snapshot) { if (take_snapshot) {
HeapIterator iterator(HeapIterator::kPreciseFiltering); HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
for (HeapObject* obj = iterator.next(); for (HeapObject* obj = iterator.next();
obj != NULL; obj != NULL;
obj = iterator.next()) { 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: public:
FreeListNodesFilter() { FreeListNodesFilter() {
MarkFreeListNodes(); MarkFreeListNodes();
} }
inline bool IsFreeListNode(HeapObject* object) { bool SkipObject(HeapObject* object) {
if (object->IsMarked()) { if (object->IsMarked()) {
object->ClearMark(); object->ClearMark();
return true; return true;
@ -4955,6 +4962,65 @@ class FreeListNodesFilter {
}; };
class UnreachableObjectsFilter : public HeapObjectsFilter {
public:
UnreachableObjectsFilter() {
MarkUnreachableObjects();
}
bool SkipObject(HeapObject* object) {
if (object->IsMarked()) {
object->ClearMark();
return true;
} else {
return false;
}
}
private:
class UnmarkingVisitor : public ObjectVisitor {
public:
UnmarkingVisitor() : list_(10) {}
void VisitPointers(Object** start, Object** end) {
for (Object** p = start; p < end; p++) {
if (!(*p)->IsHeapObject()) continue;
HeapObject* obj = HeapObject::cast(*p);
if (obj->IsMarked()) {
obj->ClearMark();
list_.Add(obj);
}
}
}
bool can_process() { return !list_.is_empty(); }
void ProcessNext() {
HeapObject* obj = list_.RemoveLast();
obj->Iterate(this);
}
private:
List<HeapObject*> list_;
};
void MarkUnreachableObjects() {
HeapIterator iterator;
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next()) {
obj->SetMark();
}
UnmarkingVisitor visitor;
Heap::IterateRoots(&visitor, VISIT_ONLY_STRONG);
while (visitor.can_process())
visitor.ProcessNext();
}
AssertNoAllocation no_alloc;
};
HeapIterator::HeapIterator() HeapIterator::HeapIterator()
: filtering_(HeapIterator::kNoFiltering), : filtering_(HeapIterator::kNoFiltering),
filter_(NULL) { filter_(NULL) {
@ -4962,7 +5028,7 @@ HeapIterator::HeapIterator()
} }
HeapIterator::HeapIterator(HeapIterator::FreeListNodesFiltering filtering) HeapIterator::HeapIterator(HeapIterator::HeapObjectsFiltering filtering)
: filtering_(filtering), : filtering_(filtering),
filter_(NULL) { filter_(NULL) {
Init(); Init();
@ -4976,12 +5042,17 @@ HeapIterator::~HeapIterator() {
void HeapIterator::Init() { void HeapIterator::Init() {
// Start the iteration. // Start the iteration.
if (filtering_ == kPreciseFiltering) { space_iterator_ = filtering_ == kNoFiltering ? new SpaceIterator :
filter_ = new FreeListNodesFilter;
space_iterator_ =
new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject); new SpaceIterator(MarkCompactCollector::SizeOfMarkedObject);
} else { switch (filtering_) {
space_iterator_ = new SpaceIterator; case kFilterFreeListNodes:
filter_ = new FreeListNodesFilter;
break;
case kFilterUnreachable:
filter_ = new UnreachableObjectsFilter;
break;
default:
break;
} }
object_iterator_ = space_iterator_->next(); object_iterator_ = space_iterator_->next();
} }
@ -4989,9 +5060,9 @@ void HeapIterator::Init() {
void HeapIterator::Shutdown() { void HeapIterator::Shutdown() {
#ifdef DEBUG #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. // objects. Otherwise, heap will be left in an inconsistent state.
if (filtering_ == kPreciseFiltering) { if (filtering_ != kNoFiltering) {
ASSERT(object_iterator_ == NULL); ASSERT(object_iterator_ == NULL);
} }
#endif #endif
@ -5008,7 +5079,7 @@ HeapObject* HeapIterator::next() {
if (filter_ == NULL) return NextObject(); if (filter_ == NULL) return NextObject();
HeapObject* obj = NextObject(); HeapObject* obj = NextObject();
while (obj != NULL && filter_->IsFreeListNode(obj)) obj = NextObject(); while (obj != NULL && filter_->SkipObject(obj)) obj = NextObject();
return obj; return obj;
} }

16
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 // 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, // phases. Also, it is forbidden to interrupt iteration in this mode,
// as this will leave heap objects marked (and thus, unusable). // as this will leave heap objects marked (and thus, unusable).
class FreeListNodesFilter; class HeapObjectsFilter;
class HeapIterator BASE_EMBEDDED { class HeapIterator BASE_EMBEDDED {
public: public:
enum FreeListNodesFiltering { enum HeapObjectsFiltering {
kNoFiltering, kNoFiltering,
kPreciseFiltering kFilterFreeListNodes,
kFilterUnreachable
}; };
HeapIterator(); HeapIterator();
explicit HeapIterator(FreeListNodesFiltering filtering); explicit HeapIterator(HeapObjectsFiltering filtering);
~HeapIterator(); ~HeapIterator();
HeapObject* next(); HeapObject* next();
@ -1608,8 +1609,8 @@ class HeapIterator BASE_EMBEDDED {
void Shutdown(); void Shutdown();
HeapObject* NextObject(); HeapObject* NextObject();
FreeListNodesFiltering filtering_; HeapObjectsFiltering filtering_;
FreeListNodesFilter* filter_; HeapObjectsFilter* filter_;
// Space iterator for iterating all the spaces. // Space iterator for iterating all the spaces.
SpaceIterator* space_iterator_; SpaceIterator* space_iterator_;
// Object iterator for the space currently being iterated. // Object iterator for the space currently being iterated.
@ -1968,6 +1969,8 @@ class GCTracer BASE_EMBEDDED {
class TranscendentalCache { class TranscendentalCache {
public: public:
enum Type {ACOS, ASIN, ATAN, COS, EXP, LOG, SIN, TAN, kNumberOfCaches}; 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); explicit TranscendentalCache(Type t);
@ -2056,7 +2059,6 @@ class TranscendentalCache {
friend class ExternalReference; friend class ExternalReference;
// Inline implementation of the cache. // Inline implementation of the cache.
friend class TranscendentalCacheStub; friend class TranscendentalCacheStub;
friend class TranscendentalCacheSSE2Stub;
static TranscendentalCache* caches_[kNumberOfCaches]; static TranscendentalCache* caches_[kNumberOfCaches];
Element elements_[kCacheSize]; Element elements_[kCacheSize];

7
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 { void HGoto::PrintDataTo(StringStream* stream) const {
stream->Add("B%d", FirstSuccessor()->block_id()); stream->Add("B%d", FirstSuccessor()->block_id());
} }

6
deps/v8/src/hydrogen-instructions.h

@ -905,6 +905,8 @@ class HCompareMapAndBranch: public HUnaryControlInstruction {
virtual HBasicBlock* FirstSuccessor() const { return true_destination_; } virtual HBasicBlock* FirstSuccessor() const { return true_destination_; }
virtual HBasicBlock* SecondSuccessor() const { return false_destination_; } virtual HBasicBlock* SecondSuccessor() const { return false_destination_; }
virtual void PrintDataTo(StringStream* stream) const;
Handle<Map> map() const { return map_; } Handle<Map> map() const { return map_; }
DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch") DECLARE_CONCRETE_INSTRUCTION(CompareMapAndBranch, "compare_map_and_branch")
@ -1387,6 +1389,8 @@ class HUnaryMathOperation: public HUnaryOperation {
case kMathSqrt: case kMathSqrt:
case kMathPowHalf: case kMathPowHalf:
case kMathLog: case kMathLog:
case kMathSin:
case kMathCos:
set_representation(Representation::Double()); set_representation(Representation::Double());
break; break;
default: default:
@ -1409,6 +1413,8 @@ class HUnaryMathOperation: public HUnaryOperation {
case kMathSqrt: case kMathSqrt:
case kMathPowHalf: case kMathPowHalf:
case kMathLog: case kMathLog:
case kMathSin:
case kMathCos:
return Representation::Double(); return Representation::Double();
break; break;
case kMathAbs: case kMathAbs:

12
deps/v8/src/hydrogen.cc

@ -3165,6 +3165,9 @@ HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object,
if (lookup->type() == MAP_TRANSITION) { if (lookup->type() == MAP_TRANSITION) {
Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); Handle<Map> transition(lookup->GetTransitionMapFromMap(*type));
instr->set_transition(transition); 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; return instr;
} }
@ -3529,9 +3532,10 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
maps.Add(map); maps.Add(map);
HSubgraph* subgraph = CreateBranchSubgraph(environment()); HSubgraph* subgraph = CreateBranchSubgraph(environment());
SubgraphScope scope(this, subgraph); SubgraphScope scope(this, subgraph);
HInstruction* instr = HLoadNamedField* instr =
BuildLoadNamedField(object, expr, map, &lookup, false); BuildLoadNamedField(object, expr, map, &lookup, false);
instr->set_position(expr->position()); instr->set_position(expr->position());
instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads.
PushAndAdd(instr); PushAndAdd(instr);
subgraphs.Add(subgraph); subgraphs.Add(subgraph);
} else { } else {
@ -3570,7 +3574,7 @@ void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
} }
HInstruction* HGraphBuilder::BuildLoadNamedField(HValue* object, HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
Property* expr, Property* expr,
Handle<Map> type, Handle<Map> type,
LookupResult* lookup, LookupResult* lookup,
@ -4093,6 +4097,8 @@ bool HGraphBuilder::TryMathFunctionInline(Call* expr) {
case kMathAbs: case kMathAbs:
case kMathSqrt: case kMathSqrt:
case kMathLog: case kMathLog:
case kMathSin:
case kMathCos:
if (argument_count == 2) { if (argument_count == 2) {
HValue* argument = Pop(); HValue* argument = Pop();
Drop(1); // Receiver. Drop(1); // Receiver.
@ -4169,7 +4175,7 @@ bool HGraphBuilder::TryCallApply(Call* expr) {
if (args->length() != 2) return false; if (args->length() != 2) return false;
VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 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()); HValue* arg_two_value = environment()->Lookup(arg_two->var());
if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;

2
deps/v8/src/hydrogen.h

@ -786,7 +786,7 @@ class HGraphBuilder: public AstVisitor {
HValue* left, HValue* left,
HValue* right); HValue* right);
HInstruction* BuildIncrement(HValue* value, bool increment); HInstruction* BuildIncrement(HValue* value, bool increment);
HInstruction* BuildLoadNamedField(HValue* object, HLoadNamedField* BuildLoadNamedField(HValue* object,
Property* expr, Property* expr,
Handle<Map> type, Handle<Map> type,
LookupResult* result, LookupResult* result,

232
deps/v8/src/ia32/code-stubs-ia32.cc

@ -2472,12 +2472,25 @@ void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
void TranscendentalCacheStub::Generate(MacroAssembler* masm) { void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
// Input on stack: // TAGGED case:
// esp[4]: argument (should be number). // Input:
// esp[4]: tagged number input argument (should be number).
// esp[0]: return address. // esp[0]: return address.
// Test that eax is a number. // 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;
Label runtime_call_clear_stack; Label runtime_call_clear_stack;
Label skip_cache;
const bool tagged = (argument_type_ == TAGGED);
if (tagged) {
// Test that eax is a number.
NearLabel input_not_smi; NearLabel input_not_smi;
NearLabel loaded; NearLabel loaded;
__ mov(eax, Operand(esp, kPointerSize)); __ mov(eax, Operand(esp, kPointerSize));
@ -2506,7 +2519,18 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset)); __ mov(ebx, FieldOperand(eax, HeapNumber::kMantissaOffset));
__ bind(&loaded); __ bind(&loaded);
// ST[0] == double value } 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);
}
// ST[0] or xmm1 == double value
// ebx = low 32 bits of double value // ebx = low 32 bits of double value
// edx = high 32 bits of double value // edx = high 32 bits of double value
// Compute hash (the shifts are arithmetic): // Compute hash (the shifts are arithmetic):
@ -2522,7 +2546,7 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize)); ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
__ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1)); __ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
// ST[0] == double value. // ST[0] or xmm1 == double value.
// ebx = low 32 bits of double value. // ebx = low 32 bits of double value.
// edx = high 32 bits of double value. // edx = high 32 bits of double value.
// ecx = TranscendentalCache::hash(double value). // ecx = TranscendentalCache::hash(double value).
@ -2559,31 +2583,80 @@ void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
__ j(not_equal, &cache_miss); __ j(not_equal, &cache_miss);
// Cache hit! // Cache hit!
__ mov(eax, Operand(ecx, 2 * kIntSize)); __ mov(eax, Operand(ecx, 2 * kIntSize));
if (tagged) {
__ fstp(0); __ fstp(0);
__ ret(kPointerSize); __ ret(kPointerSize);
} else { // UNTAGGED.
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
}
__ bind(&cache_miss); __ bind(&cache_miss);
// Update cache with new value. // Update cache with new value.
// We are short on registers, so use no_reg as scratch. // We are short on registers, so use no_reg as scratch.
// This gives slightly larger code. // This gives slightly larger code.
if (tagged) {
__ AllocateHeapNumber(eax, edi, no_reg, &runtime_call_clear_stack); __ 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); GenerateOperation(masm);
__ mov(Operand(ecx, 0), ebx); __ mov(Operand(ecx, 0), ebx);
__ mov(Operand(ecx, kIntSize), edx); __ mov(Operand(ecx, kIntSize), edx);
__ mov(Operand(ecx, 2 * kIntSize), eax); __ mov(Operand(ecx, 2 * kIntSize), eax);
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
if (tagged) {
__ ret(kPointerSize); __ 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();
}
// Call runtime, doing whatever allocation and cleanup is necessary.
if (tagged) {
__ bind(&runtime_call_clear_stack); __ bind(&runtime_call_clear_stack);
__ fstp(0); __ fstp(0);
__ bind(&runtime_call); __ bind(&runtime_call);
__ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1); __ 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() { Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
switch (type_) { switch (type_) {
// Add more cases when necessary.
case TranscendentalCache::SIN: return Runtime::kMath_sin; case TranscendentalCache::SIN: return Runtime::kMath_sin;
case TranscendentalCache::COS: return Runtime::kMath_cos; case TranscendentalCache::COS: return Runtime::kMath_cos;
case TranscendentalCache::LOG: return Runtime::kMath_log; case TranscendentalCache::LOG: return Runtime::kMath_log;
@ -2596,14 +2669,14 @@ Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) { void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
// Only free register is edi. // Only free register is edi.
// Input value is on FP stack, and also in ebx/edx. Address of result // Input value is on FP stack, and also in ebx/edx.
// (a newly allocated HeapNumber) is in eax. // Input value is possibly in xmm1.
NearLabel done; // Address of result (a newly allocated HeapNumber) may be in eax.
if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) { if (type_ == TranscendentalCache::SIN || type_ == TranscendentalCache::COS) {
// Both fsin and fcos require arguments in the range +/-2^63 and // Both fsin and fcos require arguments in the range +/-2^63 and
// return NaN for infinities and NaN. They can share all code except // return NaN for infinities and NaN. They can share all code except
// the actual fsin/fcos operation. // 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 // If argument is outside the range -2^63..2^63, fsin/cos doesn't
// work. We must reduce it to the appropriate range. // work. We must reduce it to the appropriate range.
__ mov(edi, edx); __ mov(edi, edx);
@ -2683,145 +2756,6 @@ void TranscendentalCacheStub::GenerateOperation(MacroAssembler* masm) {
} }
void TranscendentalCacheSSE2Stub::Generate(MacroAssembler* masm) {
// Input on stack:
// esp[0]: return address.
// Input in registers:
// xmm1: untagged double input argument.
// Output:
// xmm1: untagged double result.
Label skip_cache;
Label call_runtime;
// Input is an untagged double in xmm1.
// Compute hash (the shifts are arithmetic):
// h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
if (CpuFeatures::IsSupported(SSE4_1)) {
CpuFeatures::Scope sse4_scope(SSE4_1);
__ pextrd(Operand(edx), xmm1, 0x1); // copy xmm1[63..32] to edx.
} else {
__ pshufd(xmm0, xmm1, 0x1);
__ movd(Operand(edx), xmm0);
}
__ movd(Operand(ebx), xmm1);
// xmm1 = double value
// ebx = low 32 bits of double value
// edx = high 32 bits of double value
// Compute hash (the shifts are arithmetic):
// h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
__ mov(ecx, ebx);
__ xor_(ecx, Operand(edx));
__ mov(eax, ecx);
__ sar(eax, 16);
__ xor_(ecx, Operand(eax));
__ mov(eax, ecx);
__ sar(eax, 8);
__ xor_(ecx, Operand(eax));
ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
__ and_(Operand(ecx), Immediate(TranscendentalCache::kCacheSize - 1));
// xmm1 = double value.
// ebx = low 32 bits of double value.
// edx = high 32 bits of double value.
// ecx = TranscendentalCache::hash(double value).
__ mov(eax,
Immediate(ExternalReference::transcendental_cache_array_address()));
// Eax points to cache array.
__ mov(eax, Operand(eax, type_ * sizeof(TranscendentalCache::caches_[0])));
// Eax points to the cache for the type type_.
// If NULL, the cache hasn't been initialized yet, so go through runtime.
__ test(eax, Operand(eax));
__ j(zero, &call_runtime);
#ifdef DEBUG
// Check that the layout of cache elements match expectations.
{ TranscendentalCache::Element test_elem[2];
char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
CHECK_EQ(0, elem_in0 - elem_start);
CHECK_EQ(kIntSize, elem_in1 - elem_start);
CHECK_EQ(2 * kIntSize, elem_out - elem_start);
}
#endif
// Find the address of the ecx'th entry in the cache, i.e., &eax[ecx*12].
__ lea(ecx, Operand(ecx, ecx, times_2, 0));
__ lea(ecx, Operand(eax, ecx, times_4, 0));
// Check if cache matches: Double value is stored in uint32_t[2] array.
NearLabel cache_miss;
__ cmp(ebx, Operand(ecx, 0));
__ j(not_equal, &cache_miss);
__ cmp(edx, Operand(ecx, kIntSize));
__ j(not_equal, &cache_miss);
// Cache hit!
__ mov(eax, Operand(ecx, 2 * kIntSize));
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
__ bind(&cache_miss);
// Update cache with new value.
// We are short on registers, so use no_reg as scratch.
// This gives slightly larger code.
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
__ fld_d(Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
GenerateOperation(masm);
__ mov(Operand(ecx, 0), ebx);
__ mov(Operand(ecx, kIntSize), edx);
__ mov(Operand(ecx, 2 * kIntSize), eax);
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
__ bind(&skip_cache);
__ sub(Operand(esp), Immediate(kDoubleSize));
__ movdbl(Operand(esp, 0), xmm1);
__ fld_d(Operand(esp, 0));
GenerateOperation(masm);
__ fstp_d(Operand(esp, 0));
__ movdbl(xmm1, Operand(esp, 0));
__ add(Operand(esp), Immediate(kDoubleSize));
__ Ret();
__ bind(&call_runtime);
__ AllocateHeapNumber(eax, edi, no_reg, &skip_cache);
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm1);
__ EnterInternalFrame();
__ push(eax);
__ CallRuntime(RuntimeFunction(), 1);
__ LeaveInternalFrame();
__ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
__ Ret();
}
Runtime::FunctionId TranscendentalCacheSSE2Stub::RuntimeFunction() {
switch (type_) {
// Add more cases when necessary.
case TranscendentalCache::LOG: return Runtime::kMath_log;
default:
UNIMPLEMENTED();
return Runtime::kAbort;
}
}
void TranscendentalCacheSSE2Stub::GenerateOperation(MacroAssembler* masm) {
// Only free register is edi.
// Input value is on FP stack and in xmm1.
ASSERT(type_ == TranscendentalCache::LOG);
__ fldln2();
__ fxch();
__ fyl2x();
}
// Get the integer part of a heap number. Surprisingly, all this bit twiddling // 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. // 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 // Trashes edi and ebx. Dest is ecx. Source cannot be ecx or one of the

29
deps/v8/src/ia32/code-stubs-ia32.h

@ -40,32 +40,21 @@ namespace internal {
// TranscendentalCache runtime function. // TranscendentalCache runtime function.
class TranscendentalCacheStub: public CodeStub { class TranscendentalCacheStub: public CodeStub {
public: public:
explicit TranscendentalCacheStub(TranscendentalCache::Type type) enum ArgumentType {
: type_(type) {} TAGGED = 0,
void Generate(MacroAssembler* masm); UNTAGGED = 1 << TranscendentalCache::kTranscendentalTypeBits
private:
TranscendentalCache::Type type_;
Major MajorKey() { return TranscendentalCache; }
int MinorKey() { return type_; }
Runtime::FunctionId RuntimeFunction();
void GenerateOperation(MacroAssembler* masm);
}; };
explicit TranscendentalCacheStub(TranscendentalCache::Type type,
// Check the transcendental cache, or generate the result, using SSE2. ArgumentType argument_type)
// The argument and result will be in xmm1. : type_(type), argument_type_(argument_type) {}
// Only supports TranscendentalCache::LOG at this point.
class TranscendentalCacheSSE2Stub: public CodeStub {
public:
explicit TranscendentalCacheSSE2Stub(TranscendentalCache::Type type)
: type_(type) {}
void Generate(MacroAssembler* masm); void Generate(MacroAssembler* masm);
private: private:
TranscendentalCache::Type type_; TranscendentalCache::Type type_;
ArgumentType argument_type_;
Major MajorKey() { return TranscendentalCacheSSE2; } Major MajorKey() { return TranscendentalCache; }
int MinorKey() { return type_; } int MinorKey() { return type_ | argument_type_; }
Runtime::FunctionId RuntimeFunction(); Runtime::FunctionId RuntimeFunction();
void GenerateOperation(MacroAssembler* masm); void GenerateOperation(MacroAssembler* masm);
}; };

9
deps/v8/src/ia32/codegen-ia32.cc

@ -7912,7 +7912,8 @@ void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
Load(args->at(0)); Load(args->at(0));
TranscendentalCacheStub stub(TranscendentalCache::SIN); TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1); Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result); frame_->Push(&result);
} }
@ -7921,7 +7922,8 @@ void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
Load(args->at(0)); Load(args->at(0));
TranscendentalCacheStub stub(TranscendentalCache::COS); TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1); Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result); frame_->Push(&result);
} }
@ -7930,7 +7932,8 @@ void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) { void CodeGenerator::GenerateMathLog(ZoneList<Expression*>* args) {
ASSERT_EQ(args->length(), 1); ASSERT_EQ(args->length(), 1);
Load(args->at(0)); Load(args->at(0));
TranscendentalCacheStub stub(TranscendentalCache::LOG); TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED);
Result result = frame_->CallStub(&stub, 1); Result result = frame_->CallStub(&stub, 1);
frame_->Push(&result); frame_->Push(&result);
} }

9
deps/v8/src/ia32/full-codegen-ia32.cc

@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitStringCompare(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::SIN); TranscendentalCacheStub stub(TranscendentalCache::SIN,
TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3077,7 +3078,8 @@ void FullCodeGenerator::EmitMathSin(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::COS); TranscendentalCacheStub stub(TranscendentalCache::COS,
TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);
@ -3087,7 +3089,8 @@ void FullCodeGenerator::EmitMathCos(ZoneList<Expression*>* args) {
void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) { void FullCodeGenerator::EmitMathLog(ZoneList<Expression*>* args) {
// Load the argument on the stack and call the stub. // Load the argument on the stack and call the stub.
TranscendentalCacheStub stub(TranscendentalCache::LOG); TranscendentalCacheStub stub(TranscendentalCache::LOG,
TranscendentalCacheStub::TAGGED);
ASSERT(args->length() == 1); ASSERT(args->length() == 1);
VisitForStackValue(args->at(0)); VisitForStackValue(args->at(0));
__ CallStub(&stub); __ CallStub(&stub);

28
deps/v8/src/ia32/lithium-codegen-ia32.cc

@ -686,7 +686,8 @@ void LCodeGen::DoCallStub(LCallStub* instr) {
break; break;
} }
case CodeStub::TranscendentalCache: { case CodeStub::TranscendentalCache: {
TranscendentalCacheStub stub(instr->transcendental_type()); TranscendentalCacheStub stub(instr->transcendental_type(),
TranscendentalCacheStub::TAGGED);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
break; break;
} }
@ -2314,7 +2315,24 @@ void LCodeGen::DoPower(LPower* instr) {
void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 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); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} }
@ -2336,6 +2354,12 @@ void LCodeGen::DoUnaryMathOperation(LUnaryMathOperation* instr) {
case kMathPowHalf: case kMathPowHalf:
DoMathPowHalf(instr); DoMathPowHalf(instr);
break; break;
case kMathCos:
DoMathCos(instr);
break;
case kMathSin:
DoMathSin(instr);
break;
case kMathLog: case kMathLog:
DoMathLog(instr); DoMathLog(instr);
break; break;

2
deps/v8/src/ia32/lithium-codegen-ia32.h

@ -177,6 +177,8 @@ class LCodeGen BASE_EMBEDDED {
void DoMathSqrt(LUnaryMathOperation* instr); void DoMathSqrt(LUnaryMathOperation* instr);
void DoMathPowHalf(LUnaryMathOperation* instr); void DoMathPowHalf(LUnaryMathOperation* instr);
void DoMathLog(LUnaryMathOperation* instr); void DoMathLog(LUnaryMathOperation* instr);
void DoMathCos(LUnaryMathOperation* instr);
void DoMathSin(LUnaryMathOperation* instr);
// Support for recording safepoint and position information. // Support for recording safepoint and position information.
void RecordSafepoint(LPointerMap* pointers, int deoptimization_index); void RecordSafepoint(LPointerMap* pointers, int deoptimization_index);

2
deps/v8/src/ia32/lithium-ia32.cc

@ -1361,7 +1361,7 @@ LInstruction* LChunkBuilder::DoCallConstantFunction(
LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) {
BuiltinFunctionId op = instr->op(); BuiltinFunctionId op = instr->op();
if (op == kMathLog) { if (op == kMathLog || op == kMathSin || op == kMathCos) {
LOperand* input = UseFixedDouble(instr->value(), xmm1); LOperand* input = UseFixedDouble(instr->value(), xmm1);
LInstruction* result = new LUnaryMathOperation(input); LInstruction* result = new LUnaryMathOperation(input);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr); return MarkAsCall(DefineFixedDouble(result, xmm1), instr);

826
deps/v8/src/objects-debug.cc

File diff suppressed because it is too large

131
deps/v8/src/objects.cc

@ -553,11 +553,11 @@ Object* Object::GetPrototype() {
} }
void Object::ShortPrint() { void Object::ShortPrint(FILE* out) {
HeapStringAllocator allocator; HeapStringAllocator allocator;
StringStream accumulator(&allocator); StringStream accumulator(&allocator);
ShortPrint(&accumulator); ShortPrint(&accumulator);
accumulator.OutputToStdOut(); accumulator.OutputToFile(out);
} }
@ -572,8 +572,8 @@ void Object::ShortPrint(StringStream* accumulator) {
} }
void Smi::SmiPrint() { void Smi::SmiPrint(FILE* out) {
PrintF("%d", value()); PrintF(out, "%d", value());
} }
@ -587,8 +587,8 @@ void Failure::FailurePrint(StringStream* accumulator) {
} }
void Failure::FailurePrint() { void Failure::FailurePrint(FILE* out) {
PrintF("Failure(%p)", reinterpret_cast<void*>(value())); PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
} }
@ -1141,8 +1141,8 @@ Object* HeapNumber::HeapNumberToBoolean() {
} }
void HeapNumber::HeapNumberPrint() { void HeapNumber::HeapNumberPrint(FILE* out) {
PrintF("%.16g", Number()); PrintF(out, "%.16g", Number());
} }
@ -5467,9 +5467,9 @@ Object* JSFunction::SetInstanceClassName(String* name) {
} }
void JSFunction::PrintName() { void JSFunction::PrintName(FILE* out) {
SmartPointer<char> name = shared()->DebugName()->ToCString(); SmartPointer<char> name = shared()->DebugName()->ToCString();
PrintF("%s", *name); PrintF(out, "%s", *name);
} }
@ -5999,18 +5999,18 @@ Map* Code::FindFirstMap() {
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
#ifdef DEBUG #ifdef OBJECT_PRINT
void DeoptimizationInputData::DeoptimizationInputDataPrint() { void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
disasm::NameConverter converter; disasm::NameConverter converter;
int deopt_count = DeoptCount(); 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; 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++) { for (int i = 0; i < deopt_count; i++) {
int command_count = 0; int command_count = 0;
PrintF("%6d %6d %6d", PrintF(out, "%6d %6d %6d",
i, AstId(i)->value(), ArgumentsStackHeight(i)->value()); i, AstId(i)->value(), ArgumentsStackHeight(i)->value());
int translation_index = TranslationIndex(i)->value(); int translation_index = TranslationIndex(i)->value();
TranslationIterator iterator(TranslationByteArray(), translation_index); TranslationIterator iterator(TranslationByteArray(), translation_index);
@ -6019,7 +6019,8 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
ASSERT(Translation::BEGIN == opcode); ASSERT(Translation::BEGIN == opcode);
int frame_count = iterator.Next(); int frame_count = iterator.Next();
if (FLAG_print_code_verbose) { 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) { for (int i = 0; i < frame_count; ++i) {
@ -6031,10 +6032,10 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
JSFunction::cast(LiteralArray()->get(function_id)); JSFunction::cast(LiteralArray()->get(function_id));
unsigned height = iterator.Next(); unsigned height = iterator.Next();
if (FLAG_print_code_verbose) { 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); "", Translation::StringFor(opcode), ast_id);
function->PrintName(); function->PrintName(out);
PrintF(", height=%u}\n", height); PrintF(out, ", height=%u}\n", height);
} }
// Size of translation is height plus all incoming arguments including // Size of translation is height plus all incoming arguments including
@ -6044,13 +6045,13 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
for (int j = 0; j < size; ++j) { for (int j = 0; j < size; ++j) {
opcode = static_cast<Translation::Opcode>(iterator.Next()); opcode = static_cast<Translation::Opcode>(iterator.Next());
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("%24s %s ", "", Translation::StringFor(opcode)); PrintF(out, "%24s %s ", "", Translation::StringFor(opcode));
} }
if (opcode == Translation::DUPLICATE) { if (opcode == Translation::DUPLICATE) {
opcode = static_cast<Translation::Opcode>(iterator.Next()); opcode = static_cast<Translation::Opcode>(iterator.Next());
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("%s ", Translation::StringFor(opcode)); PrintF(out, "%s ", Translation::StringFor(opcode));
} }
--j; // Two commands share the same frame index. --j; // Two commands share the same frame index.
} }
@ -6065,7 +6066,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::REGISTER: { case Translation::REGISTER: {
int reg_code = iterator.Next(); int reg_code = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{input=%s}", converter.NameOfCPURegister(reg_code)); PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
} }
break; break;
} }
@ -6073,7 +6074,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::INT32_REGISTER: { case Translation::INT32_REGISTER: {
int reg_code = iterator.Next(); int reg_code = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{input=%s}", converter.NameOfCPURegister(reg_code)); PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
} }
break; break;
} }
@ -6081,7 +6082,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::DOUBLE_REGISTER: { case Translation::DOUBLE_REGISTER: {
int reg_code = iterator.Next(); int reg_code = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{input=%s}", PrintF(out, "{input=%s}",
DoubleRegister::AllocationIndexToString(reg_code)); DoubleRegister::AllocationIndexToString(reg_code));
} }
break; break;
@ -6090,7 +6091,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::STACK_SLOT: { case Translation::STACK_SLOT: {
int input_slot_index = iterator.Next(); int input_slot_index = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{input=%d}", input_slot_index); PrintF(out, "{input=%d}", input_slot_index);
} }
break; break;
} }
@ -6098,7 +6099,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::INT32_STACK_SLOT: { case Translation::INT32_STACK_SLOT: {
int input_slot_index = iterator.Next(); int input_slot_index = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{input=%d}", input_slot_index); PrintF(out, "{input=%d}", input_slot_index);
} }
break; break;
} }
@ -6106,7 +6107,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::DOUBLE_STACK_SLOT: { case Translation::DOUBLE_STACK_SLOT: {
int input_slot_index = iterator.Next(); int input_slot_index = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{input=%d}", input_slot_index); PrintF(out, "{input=%d}", input_slot_index);
} }
break; break;
} }
@ -6114,7 +6115,7 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::LITERAL: { case Translation::LITERAL: {
unsigned literal_index = iterator.Next(); unsigned literal_index = iterator.Next();
if (FLAG_print_code_verbose) { if (FLAG_print_code_verbose) {
PrintF("{literal_id=%u}", literal_index); PrintF(out, "{literal_id=%u}", literal_index);
} }
break; break;
} }
@ -6122,16 +6123,16 @@ void DeoptimizationInputData::DeoptimizationInputDataPrint() {
case Translation::ARGUMENTS_OBJECT: case Translation::ARGUMENTS_OBJECT:
break; 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() { void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
PrintF("Deoptimization Output Data (deopt points = %d)\n", PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
this->DeoptPoints()); this->DeoptPoints());
if (this->DeoptPoints() == 0) return; if (this->DeoptPoints() == 0) return;
@ -6202,56 +6203,56 @@ const char* Code::PropertyType2String(PropertyType type) {
} }
void Code::Disassemble(const char* name) { void Code::Disassemble(const char* name, FILE* out) {
PrintF("kind = %s\n", Kind2String(kind())); PrintF(out, "kind = %s\n", Kind2String(kind()));
if (is_inline_cache_stub()) { if (is_inline_cache_stub()) {
PrintF("ic_state = %s\n", ICState2String(ic_state())); PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP); PrintF(out, "ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
if (ic_state() == MONOMORPHIC) { if (ic_state() == MONOMORPHIC) {
PrintF("type = %s\n", PropertyType2String(type())); PrintF(out, "type = %s\n", PropertyType2String(type()));
} }
} }
if ((name != NULL) && (name[0] != '\0')) { if ((name != NULL) && (name[0] != '\0')) {
PrintF("name = %s\n", name); PrintF(out, "name = %s\n", name);
} }
if (kind() == OPTIMIZED_FUNCTION) { 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()); PrintF(out, "Instructions (size = %d)\n", instruction_size());
Disassembler::Decode(NULL, this); Disassembler::Decode(out, this);
PrintF("\n"); PrintF(out, "\n");
#ifdef DEBUG #ifdef DEBUG
if (kind() == FUNCTION) { if (kind() == FUNCTION) {
DeoptimizationOutputData* data = DeoptimizationOutputData* data =
DeoptimizationOutputData::cast(this->deoptimization_data()); DeoptimizationOutputData::cast(this->deoptimization_data());
data->DeoptimizationOutputDataPrint(); data->DeoptimizationOutputDataPrint(out);
} else if (kind() == OPTIMIZED_FUNCTION) { } else if (kind() == OPTIMIZED_FUNCTION) {
DeoptimizationInputData* data = DeoptimizationInputData* data =
DeoptimizationInputData::cast(this->deoptimization_data()); DeoptimizationInputData::cast(this->deoptimization_data());
data->DeoptimizationInputDataPrint(); data->DeoptimizationInputDataPrint(out);
} }
PrintF("\n"); PrintF("\n");
#endif #endif
if (kind() == OPTIMIZED_FUNCTION) { if (kind() == OPTIMIZED_FUNCTION) {
SafepointTable table(this); 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++) { for (unsigned i = 0; i < table.length(); i++) {
unsigned pc_offset = table.GetPcOffset(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); table.PrintEntry(i);
PrintF(" (sp -> fp)"); PrintF(out, " (sp -> fp)");
int deoptimization_index = table.GetDeoptimizationIndex(i); int deoptimization_index = table.GetDeoptimizationIndex(i);
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) {
PrintF(" %6d", deoptimization_index); PrintF(out, " %6d", deoptimization_index);
} else { } else {
PrintF(" <none>"); PrintF(out, " <none>");
} }
PrintF("\n"); PrintF(out, "\n");
} }
PrintF("\n"); PrintF(out, "\n");
} else if (kind() == FUNCTION) { } else if (kind() == FUNCTION) {
unsigned offset = stack_check_table_start(); unsigned offset = stack_check_table_start();
// If there is no stack check table, the "table start" will at or after // 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 = unsigned* address =
reinterpret_cast<unsigned*>(instruction_start() + offset); reinterpret_cast<unsigned*>(instruction_start() + offset);
unsigned length = address[0]; unsigned length = address[0];
PrintF("Stack checks (size = %u)\n", length); PrintF(out, "Stack checks (size = %u)\n", length);
PrintF("ast_id pc_offset\n"); PrintF(out, "ast_id pc_offset\n");
for (unsigned i = 0; i < length; ++i) { for (unsigned i = 0; i < length; ++i) {
unsigned index = (2 * i) + 1; 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()); PrintF("RelocInfo (size = %d)\n", relocation_size());
for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(); for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
PrintF("\n"); PrintF(out, "\n");
} }
#endif // ENABLE_DISASSEMBLER #endif // ENABLE_DISASSEMBLER
@ -7421,22 +7422,22 @@ bool JSObject::ShouldConvertToFastElements() {
// class. This requires us to have the template functions put // class. This requires us to have the template functions put
// together, so even though this function belongs in objects-debug.cc, // together, so even though this function belongs in objects-debug.cc,
// we keep it here instead to satisfy certain compilers. // we keep it here instead to satisfy certain compilers.
#ifdef DEBUG #ifdef OBJECT_PRINT
template<typename Shape, typename Key> template<typename Shape, typename Key>
void Dictionary<Shape, Key>::Print() { void Dictionary<Shape, Key>::Print(FILE* out) {
int capacity = HashTable<Shape, Key>::Capacity(); int capacity = HashTable<Shape, Key>::Capacity();
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { if (HashTable<Shape, Key>::IsKey(k)) {
PrintF(" "); PrintF(out, " ");
if (k->IsString()) { if (k->IsString()) {
String::cast(k)->StringPrint(); String::cast(k)->StringPrint(out);
} else { } else {
k->ShortPrint(); k->ShortPrint(out);
} }
PrintF(": "); PrintF(out, ": ");
ValueAt(i)->ShortPrint(); ValueAt(i)->ShortPrint(out);
PrintF("\n"); PrintF(out, "\n");
} }
} }
} }

343
deps/v8/src/objects.h

@ -607,10 +607,18 @@ class MaybeObject BASE_EMBEDDED {
return reinterpret_cast<Object*>(this); return reinterpret_cast<Object*>(this);
} }
#ifdef DEBUG #ifdef OBJECT_PRINT
// Prints this object with details. // Prints this object with details.
void Print(); inline void Print() {
void PrintLn(); Print(stdout);
};
inline void PrintLn() {
PrintLn(stdout);
}
void Print(FILE* out);
void PrintLn(FILE* out);
#endif
#ifdef DEBUG
// Verifies the object. // Verifies the object.
void Verify(); void Verify();
#endif #endif
@ -762,7 +770,10 @@ class Object : public MaybeObject {
#endif #endif
// Prints this object without details. // 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. // Prints this object without details to a message accumulator.
void ShortPrint(StringStream* accumulator); void ShortPrint(StringStream* accumulator);
@ -801,7 +812,10 @@ class Smi: public Object {
static inline Smi* cast(Object* object); static inline Smi* cast(Object* object);
// Dispatched behavior. // Dispatched behavior.
void SmiPrint(); inline void SmiPrint() {
SmiPrint(stdout);
}
void SmiPrint(FILE* out);
void SmiPrint(StringStream* accumulator); void SmiPrint(StringStream* accumulator);
#ifdef DEBUG #ifdef DEBUG
void SmiVerify(); void SmiVerify();
@ -870,7 +884,10 @@ class Failure: public MaybeObject {
static inline Failure* cast(MaybeObject* object); static inline Failure* cast(MaybeObject* object);
// Dispatched behavior. // Dispatched behavior.
void FailurePrint(); inline void FailurePrint() {
FailurePrint(stdout);
}
void FailurePrint(FILE* out);
void FailurePrint(StringStream* accumulator); void FailurePrint(StringStream* accumulator);
#ifdef DEBUG #ifdef DEBUG
void FailureVerify(); void FailureVerify();
@ -1099,14 +1116,23 @@ class HeapObject: public Object {
// Dispatched behavior. // Dispatched behavior.
void HeapObjectShortPrint(StringStream* accumulator); void HeapObjectShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
inline void HeapObjectPrint() {
HeapObjectPrint(stdout);
}
void HeapObjectPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void HeapObjectPrint();
void HeapObjectVerify(); void HeapObjectVerify();
inline void VerifyObjectField(int offset); inline void VerifyObjectField(int offset);
inline void VerifySmiField(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 // Verify a pointer is a valid HeapObject pointer that points to object
// areas in the heap. // areas in the heap.
static void VerifyHeapPointer(Object* p); static void VerifyHeapPointer(Object* p);
@ -1189,7 +1215,10 @@ class HeapNumber: public HeapObject {
// Dispatched behavior. // Dispatched behavior.
Object* HeapNumberToBoolean(); Object* HeapNumberToBoolean();
void HeapNumberPrint(); inline void HeapNumberPrint() {
HeapNumberPrint(stdout);
}
void HeapNumberPrint(FILE* out);
void HeapNumberPrint(StringStream* accumulator); void HeapNumberPrint(StringStream* accumulator);
#ifdef DEBUG #ifdef DEBUG
void HeapNumberVerify(); void HeapNumberVerify();
@ -1649,12 +1678,28 @@ class JSObject: public HeapObject {
// Dispatched behavior. // Dispatched behavior.
void JSObjectShortPrint(StringStream* accumulator); void JSObjectShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
inline void JSObjectPrint() {
JSObjectPrint(stdout);
}
void JSObjectPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSObjectPrint();
void JSObjectVerify(); void JSObjectVerify();
void PrintProperties(); #endif
void PrintElements(); #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. // Structure for collecting spill information about JSObjects.
class SpillInformation { class SpillInformation {
public: public:
@ -1689,7 +1734,7 @@ class JSObject: public HeapObject {
static const uint32_t kMaxGap = 1024; static const uint32_t kMaxGap = 1024;
static const int kMaxFastElementsLength = 5000; static const int kMaxFastElementsLength = 5000;
static const int kInitialMaxFastElementArray = 100000; static const int kInitialMaxFastElementArray = 100000;
static const int kMaxFastProperties = 8; static const int kMaxFastProperties = 12;
static const int kMaxInstanceSize = 255 * kPointerSize; static const int kMaxInstanceSize = 255 * kPointerSize;
// When extending the backing storage for property values, we increase // When extending the backing storage for property values, we increase
// its size by more than the 1 entry necessary, so sequentially adding fields // 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; static const int kMaxLength = (kMaxSize - kHeaderSize) / kPointerSize;
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void FixedArrayPrint() {
FixedArrayPrint(stdout);
}
void FixedArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void FixedArrayPrint();
void FixedArrayVerify(); void FixedArrayVerify();
// Checks if two FixedArrays have identical contents. // Checks if two FixedArrays have identical contents.
bool IsEqualTo(FixedArray* other); bool IsEqualTo(FixedArray* other);
@ -2012,10 +2062,15 @@ class DescriptorArray: public FixedArray {
static const int kEnumCacheBridgeCacheOffset = static const int kEnumCacheBridgeCacheOffset =
kEnumCacheBridgeEnumOffset + kPointerSize; kEnumCacheBridgeEnumOffset + kPointerSize;
#ifdef DEBUG #ifdef OBJECT_PRINT
// Print all the descriptors. // 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? // Is the descriptor array sorted and without duplicates?
bool IsSortedNoDuplicates(); bool IsSortedNoDuplicates();
@ -2396,8 +2451,11 @@ class Dictionary: public HashTable<Shape, Key> {
// Ensure enough space for n additional elements. // Ensure enough space for n additional elements.
MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key); MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
#ifdef DEBUG #ifdef OBJECT_PRINT
void Print(); inline void Print() {
Print(stdout);
}
void Print(FILE* out);
#endif #endif
// Returns the key (slow). // Returns the key (slow).
Object* SlowReverseLookup(Object* value); Object* SlowReverseLookup(Object* value);
@ -2619,8 +2677,13 @@ class ByteArray: public HeapObject {
inline int ByteArraySize() { inline int ByteArraySize() {
return SizeFor(this->length()); return SizeFor(this->length());
} }
#ifdef OBJECT_PRINT
inline void ByteArrayPrint() {
ByteArrayPrint(stdout);
}
void ByteArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ByteArrayPrint();
void ByteArrayVerify(); void ByteArrayVerify();
#endif #endif
@ -2669,8 +2732,13 @@ class PixelArray: public HeapObject {
// Casting. // Casting.
static inline PixelArray* cast(Object* obj); static inline PixelArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void PixelArrayPrint() {
PixelArrayPrint(stdout);
}
void PixelArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void PixelArrayPrint();
void PixelArrayVerify(); void PixelArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2741,8 +2809,13 @@ class ExternalByteArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalByteArray* cast(Object* obj); static inline ExternalByteArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalByteArrayPrint() {
ExternalByteArrayPrint(stdout);
}
void ExternalByteArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalByteArrayPrint();
void ExternalByteArrayVerify(); void ExternalByteArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2764,8 +2837,13 @@ class ExternalUnsignedByteArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalUnsignedByteArray* cast(Object* obj); static inline ExternalUnsignedByteArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalUnsignedByteArrayPrint() {
ExternalUnsignedByteArrayPrint(stdout);
}
void ExternalUnsignedByteArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalUnsignedByteArrayPrint();
void ExternalUnsignedByteArrayVerify(); void ExternalUnsignedByteArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2787,8 +2865,13 @@ class ExternalShortArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalShortArray* cast(Object* obj); static inline ExternalShortArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalShortArrayPrint() {
ExternalShortArrayPrint(stdout);
}
void ExternalShortArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalShortArrayPrint();
void ExternalShortArrayVerify(); void ExternalShortArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2810,8 +2893,13 @@ class ExternalUnsignedShortArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalUnsignedShortArray* cast(Object* obj); static inline ExternalUnsignedShortArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalUnsignedShortArrayPrint() {
ExternalUnsignedShortArrayPrint(stdout);
}
void ExternalUnsignedShortArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalUnsignedShortArrayPrint();
void ExternalUnsignedShortArrayVerify(); void ExternalUnsignedShortArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2833,8 +2921,13 @@ class ExternalIntArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalIntArray* cast(Object* obj); static inline ExternalIntArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalIntArrayPrint() {
ExternalIntArrayPrint(stdout);
}
void ExternalIntArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalIntArrayPrint();
void ExternalIntArrayVerify(); void ExternalIntArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2856,8 +2949,13 @@ class ExternalUnsignedIntArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalUnsignedIntArray* cast(Object* obj); static inline ExternalUnsignedIntArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalUnsignedIntArrayPrint() {
ExternalUnsignedIntArrayPrint(stdout);
}
void ExternalUnsignedIntArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalUnsignedIntArrayPrint();
void ExternalUnsignedIntArrayVerify(); void ExternalUnsignedIntArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2879,8 +2977,13 @@ class ExternalFloatArray: public ExternalArray {
// Casting. // Casting.
static inline ExternalFloatArray* cast(Object* obj); static inline ExternalFloatArray* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ExternalFloatArrayPrint() {
ExternalFloatArrayPrint(stdout);
}
void ExternalFloatArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ExternalFloatArrayPrint();
void ExternalFloatArrayVerify(); void ExternalFloatArrayVerify();
#endif // DEBUG #endif // DEBUG
@ -2960,8 +3063,8 @@ class DeoptimizationInputData: public FixedArray {
// Casting. // Casting.
static inline DeoptimizationInputData* cast(Object* obj); static inline DeoptimizationInputData* cast(Object* obj);
#ifdef DEBUG #ifdef OBJECT_PRINT
void DeoptimizationInputDataPrint(); void DeoptimizationInputDataPrint(FILE* out);
#endif #endif
private: private:
@ -2999,8 +3102,8 @@ class DeoptimizationOutputData: public FixedArray {
// Casting. // Casting.
static inline DeoptimizationOutputData* cast(Object* obj); static inline DeoptimizationOutputData* cast(Object* obj);
#ifdef DEBUG #ifdef OBJECT_PRINT
void DeoptimizationOutputDataPrint(); void DeoptimizationOutputDataPrint(FILE* out);
#endif #endif
}; };
@ -3049,7 +3152,10 @@ class Code: public HeapObject {
static const char* Kind2String(Kind kind); static const char* Kind2String(Kind kind);
static const char* ICState2String(InlineCacheState state); static const char* ICState2String(InlineCacheState state);
static const char* PropertyType2String(PropertyType type); 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 #endif // ENABLE_DISASSEMBLER
// [instruction_size]: Size of the native instructions // [instruction_size]: Size of the native instructions
@ -3242,8 +3348,13 @@ class Code: public HeapObject {
template<typename StaticVisitor> template<typename StaticVisitor>
inline void CodeIterateBody(); inline void CodeIterateBody();
#ifdef OBJECT_PRINT
inline void CodePrint() {
CodePrint(stdout);
}
void CodePrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void CodePrint();
void CodeVerify(); void CodeVerify();
#endif #endif
@ -3531,8 +3642,13 @@ class Map: public HeapObject {
void ClearNonLiveTransitions(Object* real_prototype); void ClearNonLiveTransitions(Object* real_prototype);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void MapPrint() {
MapPrint(stdout);
}
void MapPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void MapPrint();
void MapVerify(); void MapVerify();
void SharedMapVerify(); void SharedMapVerify();
#endif #endif
@ -3688,8 +3804,13 @@ class Script: public Struct {
// resource is accessible. Otherwise, always return true. // resource is accessible. Otherwise, always return true.
inline bool HasValidSource(); inline bool HasValidSource();
#ifdef OBJECT_PRINT
inline void ScriptPrint() {
ScriptPrint(stdout);
}
void ScriptPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ScriptPrint();
void ScriptVerify(); void ScriptVerify();
#endif #endif
@ -4052,8 +4173,13 @@ class SharedFunctionInfo: public HeapObject {
// Dispatched behavior. // Dispatched behavior.
// Set max_length to -1 for unlimited length. // Set max_length to -1 for unlimited length.
void SourceCodePrint(StringStream* accumulator, int max_length); void SourceCodePrint(StringStream* accumulator, int max_length);
#ifdef OBJECT_PRINT
inline void SharedFunctionInfoPrint() {
SharedFunctionInfoPrint(stdout);
}
void SharedFunctionInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void SharedFunctionInfoPrint();
void SharedFunctionInfoVerify(); void SharedFunctionInfoVerify();
#endif #endif
@ -4285,7 +4411,10 @@ class JSFunction: public JSObject {
DECL_ACCESSORS(next_function_link, Object) DECL_ACCESSORS(next_function_link, Object)
// Prints the name of the function using PrintF. // Prints the name of the function using PrintF.
void PrintName(); inline void PrintName() {
PrintName(stdout);
}
void PrintName(FILE* out);
// Casting. // Casting.
static inline JSFunction* cast(Object* obj); static inline JSFunction* cast(Object* obj);
@ -4295,8 +4424,13 @@ class JSFunction: public JSObject {
void JSFunctionIterateBody(int object_size, ObjectVisitor* v); void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSFunctionPrint() {
JSFunctionPrint(stdout);
}
void JSFunctionPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSFunctionPrint();
void JSFunctionVerify(); void JSFunctionVerify();
#endif #endif
@ -4345,8 +4479,13 @@ class JSGlobalProxy : public JSObject {
static inline JSGlobalProxy* cast(Object* obj); static inline JSGlobalProxy* cast(Object* obj);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSGlobalProxyPrint() {
JSGlobalProxyPrint(stdout);
}
void JSGlobalProxyPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSGlobalProxyPrint();
void JSGlobalProxyVerify(); void JSGlobalProxyVerify();
#endif #endif
@ -4416,8 +4555,13 @@ class JSGlobalObject: public GlobalObject {
static inline JSGlobalObject* cast(Object* obj); static inline JSGlobalObject* cast(Object* obj);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSGlobalObjectPrint() {
JSGlobalObjectPrint(stdout);
}
void JSGlobalObjectPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSGlobalObjectPrint();
void JSGlobalObjectVerify(); void JSGlobalObjectVerify();
#endif #endif
@ -4445,8 +4589,13 @@ class JSBuiltinsObject: public GlobalObject {
static inline JSBuiltinsObject* cast(Object* obj); static inline JSBuiltinsObject* cast(Object* obj);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSBuiltinsObjectPrint() {
JSBuiltinsObjectPrint(stdout);
}
void JSBuiltinsObjectPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSBuiltinsObjectPrint();
void JSBuiltinsObjectVerify(); void JSBuiltinsObjectVerify();
#endif #endif
@ -4483,8 +4632,13 @@ class JSValue: public JSObject {
static inline JSValue* cast(Object* obj); static inline JSValue* cast(Object* obj);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSValuePrint() {
JSValuePrint(stdout);
}
void JSValuePrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSValuePrint();
void JSValueVerify(); void JSValueVerify();
#endif #endif
@ -4673,8 +4827,13 @@ class CodeCache: public Struct {
static inline CodeCache* cast(Object* obj); static inline CodeCache* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void CodeCachePrint() {
CodeCachePrint(stdout);
}
void CodeCachePrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void CodeCachePrint();
void CodeCacheVerify(); void CodeCacheVerify();
#endif #endif
@ -4975,8 +5134,13 @@ class String: public HeapObject {
// Dispatched behavior. // Dispatched behavior.
void StringShortPrint(StringStream* accumulator); void StringShortPrint(StringStream* accumulator);
#ifdef OBJECT_PRINT
inline void StringPrint() {
StringPrint(stdout);
}
void StringPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void StringPrint();
void StringVerify(); void StringVerify();
#endif #endif
inline bool IsFlat(); inline bool IsFlat();
@ -5531,7 +5695,12 @@ class JSGlobalPropertyCell: public HeapObject {
#ifdef DEBUG #ifdef DEBUG
void JSGlobalPropertyCellVerify(); void JSGlobalPropertyCellVerify();
void JSGlobalPropertyCellPrint(); #endif
#ifdef OBJECT_PRINT
inline void JSGlobalPropertyCellPrint() {
JSGlobalPropertyCellPrint(stdout);
}
void JSGlobalPropertyCellPrint(FILE* out);
#endif #endif
// Layout description. // Layout description.
@ -5566,8 +5735,13 @@ class Proxy: public HeapObject {
template<typename StaticVisitor> template<typename StaticVisitor>
inline void ProxyIterateBody(); inline void ProxyIterateBody();
#ifdef OBJECT_PRINT
inline void ProxyPrint() {
ProxyPrint(stdout);
}
void ProxyPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ProxyPrint();
void ProxyVerify(); void ProxyVerify();
#endif #endif
@ -5616,8 +5790,13 @@ class JSArray: public JSObject {
inline void EnsureSize(int minimum_size_of_backing_fixed_array); inline void EnsureSize(int minimum_size_of_backing_fixed_array);
// Dispatched behavior. // Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSArrayPrint() {
JSArrayPrint(stdout);
}
void JSArrayPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void JSArrayPrint();
void JSArrayVerify(); void JSArrayVerify();
#endif #endif
@ -5688,8 +5867,13 @@ class AccessorInfo: public Struct {
static inline AccessorInfo* cast(Object* obj); static inline AccessorInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void AccessorInfoPrint() {
AccessorInfoPrint(stdout);
}
void AccessorInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void AccessorInfoPrint();
void AccessorInfoVerify(); void AccessorInfoVerify();
#endif #endif
@ -5719,8 +5903,13 @@ class AccessCheckInfo: public Struct {
static inline AccessCheckInfo* cast(Object* obj); static inline AccessCheckInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void AccessCheckInfoPrint() {
AccessCheckInfoPrint(stdout);
}
void AccessCheckInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void AccessCheckInfoPrint();
void AccessCheckInfoVerify(); void AccessCheckInfoVerify();
#endif #endif
@ -5745,8 +5934,13 @@ class InterceptorInfo: public Struct {
static inline InterceptorInfo* cast(Object* obj); static inline InterceptorInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void InterceptorInfoPrint() {
InterceptorInfoPrint(stdout);
}
void InterceptorInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void InterceptorInfoPrint();
void InterceptorInfoVerify(); void InterceptorInfoVerify();
#endif #endif
@ -5770,8 +5964,13 @@ class CallHandlerInfo: public Struct {
static inline CallHandlerInfo* cast(Object* obj); static inline CallHandlerInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void CallHandlerInfoPrint() {
CallHandlerInfoPrint(stdout);
}
void CallHandlerInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void CallHandlerInfoPrint();
void CallHandlerInfoVerify(); void CallHandlerInfoVerify();
#endif #endif
@ -5827,8 +6026,13 @@ class FunctionTemplateInfo: public TemplateInfo {
static inline FunctionTemplateInfo* cast(Object* obj); static inline FunctionTemplateInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void FunctionTemplateInfoPrint() {
FunctionTemplateInfoPrint(stdout);
}
void FunctionTemplateInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void FunctionTemplateInfoPrint();
void FunctionTemplateInfoVerify(); void FunctionTemplateInfoVerify();
#endif #endif
@ -5870,8 +6074,13 @@ class ObjectTemplateInfo: public TemplateInfo {
static inline ObjectTemplateInfo* cast(Object* obj); static inline ObjectTemplateInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void ObjectTemplateInfoPrint() {
ObjectTemplateInfoPrint(stdout);
}
void ObjectTemplateInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void ObjectTemplateInfoPrint();
void ObjectTemplateInfoVerify(); void ObjectTemplateInfoVerify();
#endif #endif
@ -5889,8 +6098,13 @@ class SignatureInfo: public Struct {
static inline SignatureInfo* cast(Object* obj); static inline SignatureInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void SignatureInfoPrint() {
SignatureInfoPrint(stdout);
}
void SignatureInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void SignatureInfoPrint();
void SignatureInfoVerify(); void SignatureInfoVerify();
#endif #endif
@ -5909,8 +6123,13 @@ class TypeSwitchInfo: public Struct {
static inline TypeSwitchInfo* cast(Object* obj); static inline TypeSwitchInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void TypeSwitchInfoPrint() {
TypeSwitchInfoPrint(stdout);
}
void TypeSwitchInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void TypeSwitchInfoPrint();
void TypeSwitchInfoVerify(); void TypeSwitchInfoVerify();
#endif #endif
@ -5956,8 +6175,13 @@ class DebugInfo: public Struct {
static inline DebugInfo* cast(Object* obj); static inline DebugInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void DebugInfoPrint() {
DebugInfoPrint(stdout);
}
void DebugInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void DebugInfoPrint();
void DebugInfoVerify(); void DebugInfoVerify();
#endif #endif
@ -6009,8 +6233,13 @@ class BreakPointInfo: public Struct {
static inline BreakPointInfo* cast(Object* obj); static inline BreakPointInfo* cast(Object* obj);
#ifdef OBJECT_PRINT
inline void BreakPointInfoPrint() {
BreakPointInfoPrint(stdout);
}
void BreakPointInfoPrint(FILE* out);
#endif
#ifdef DEBUG #ifdef DEBUG
void BreakPointInfoPrint();
void BreakPointInfoVerify(); void BreakPointInfoVerify();
#endif #endif

4
deps/v8/src/parser.cc

@ -3730,7 +3730,7 @@ RegExpParser::RegExpParser(FlatStringReader* in,
contains_anchor_(false), contains_anchor_(false),
is_scanned_for_captures_(false), is_scanned_for_captures_(false),
failed_(false) { failed_(false) {
Advance(1); Advance();
} }
@ -3768,7 +3768,7 @@ void RegExpParser::Reset(int pos) {
void RegExpParser::Advance(int dist) { void RegExpParser::Advance(int dist) {
for (int i = 0; i < dist; i++) next_pos_ += dist - 1;
Advance(); Advance();
} }

13
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. // Print error message to console.
void OS::PrintError(const char* format, ...) { void OS::PrintError(const char* format, ...) {
// Minimalistic implementation for bootstrapping. // Minimalistic implementation for bootstrapping.

27
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, ...) { void OS::PrintError(const char* format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
@ -173,6 +190,8 @@ int OS::VSNPrintF(Vector<char> str,
va_list args) { va_list args) {
int n = vsnprintf(str.start(), str.length(), format, args); int n = vsnprintf(str.start(), str.length(), format, args);
if (n < 0 || n >= str.length()) { if (n < 0 || n >= str.length()) {
// If the length is zero, the assignment fails.
if (str.length() > 0)
str[str.length() - 1] = '\0'; str[str.length() - 1] = '\0';
return -1; return -1;
} else { } else {
@ -204,6 +223,14 @@ class POSIXSocket : public Socket {
explicit POSIXSocket() { explicit POSIXSocket() {
// Create the socket. // Create the socket.
socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 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) { } explicit POSIXSocket(int socket): socket_(socket) { }
virtual ~POSIXSocket() { Shutdown(); } virtual ~POSIXSocket() { Shutdown(); }

14
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. // Print error message to console.
void OS::PrintError(const char* format, ...) { void OS::PrintError(const char* format, ...) {
va_list args; va_list args;
@ -716,6 +729,7 @@ int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) {
// Make sure to zero-terminate the string if the output was // Make sure to zero-terminate the string if the output was
// truncated or if there was an error. // truncated or if there was an error.
if (n < 0 || n >= str.length()) { if (n < 0 || n >= str.length()) {
if (str.length() > 0)
str[str.length() - 1] = '\0'; str[str.length() - 1] = '\0';
return -1; return -1;
} else { } else {

4
deps/v8/src/platform.h

@ -184,6 +184,10 @@ class OS {
static void Print(const char* format, ...); static void Print(const char* format, ...);
static void VPrint(const char* format, va_list args); 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 // Print error output to console. This is mostly used for error message
// output. On platforms that has standard terminal output, the output // output. On platforms that has standard terminal output, the output
// should go to stderr. // should go to stderr.

8
deps/v8/src/profile-generator.cc

@ -2218,7 +2218,7 @@ void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) {
void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) { void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
if (control_ == NULL) return; if (control_ == NULL) return;
HeapIterator iterator(HeapIterator::kPreciseFiltering); HeapIterator iterator(HeapIterator::kFilterUnreachable);
int objects_count = 0; int objects_count = 0;
for (HeapObject* obj = iterator.next(); for (HeapObject* obj = iterator.next();
obj != NULL; obj != NULL;
@ -2342,8 +2342,6 @@ bool HeapSnapshotGenerator::SetEntriesDominators() {
ASSERT(dominators[i] != NULL); ASSERT(dominators[i] != NULL);
ordered_entries[i]->set_dominator(dominators[i]); ordered_entries[i]->set_dominator(dominators[i]);
} }
// For nodes unreachable from root, set dominator to itself.
snapshot_->SetDominatorsToSelf();
return true; return true;
} }
@ -2373,9 +2371,9 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
bool HeapSnapshotGenerator::IterateAndExtractReferences() { bool HeapSnapshotGenerator::IterateAndExtractReferences() {
HeapIterator iterator(HeapIterator::kPreciseFiltering); HeapIterator iterator(HeapIterator::kFilterUnreachable);
bool interrupted = false; 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(); for (HeapObject* obj = iterator.next();
obj != NULL; obj != NULL;
obj = iterator.next(), IncProgressCounter()) { obj = iterator.next(), IncProgressCounter()) {

62
deps/v8/src/property.cc

@ -31,62 +31,62 @@ namespace v8 {
namespace internal { namespace internal {
#ifdef DEBUG #ifdef OBJECT_PRINT
void LookupResult::Print() { void LookupResult::Print(FILE* out) {
if (!IsFound()) { if (!IsFound()) {
PrintF("Not Found\n"); PrintF(out, "Not Found\n");
return; return;
} }
PrintF("LookupResult:\n"); PrintF(out, "LookupResult:\n");
PrintF(" -cacheable = %s\n", IsCacheable() ? "true" : "false"); PrintF(out, " -cacheable = %s\n", IsCacheable() ? "true" : "false");
PrintF(" -attributes = %x\n", GetAttributes()); PrintF(out, " -attributes = %x\n", GetAttributes());
switch (type()) { switch (type()) {
case NORMAL: case NORMAL:
PrintF(" -type = normal\n"); PrintF(out, " -type = normal\n");
PrintF(" -entry = %d", GetDictionaryEntry()); PrintF(out, " -entry = %d", GetDictionaryEntry());
break; break;
case MAP_TRANSITION: case MAP_TRANSITION:
PrintF(" -type = map transition\n"); PrintF(out, " -type = map transition\n");
PrintF(" -map:\n"); PrintF(out, " -map:\n");
GetTransitionMap()->Print(); GetTransitionMap()->Print(out);
PrintF("\n"); PrintF(out, "\n");
break; break;
case CONSTANT_FUNCTION: case CONSTANT_FUNCTION:
PrintF(" -type = constant function\n"); PrintF(out, " -type = constant function\n");
PrintF(" -function:\n"); PrintF(out, " -function:\n");
GetConstantFunction()->Print(); GetConstantFunction()->Print(out);
PrintF("\n"); PrintF(out, "\n");
break; break;
case FIELD: case FIELD:
PrintF(" -type = field\n"); PrintF(out, " -type = field\n");
PrintF(" -index = %d", GetFieldIndex()); PrintF(out, " -index = %d", GetFieldIndex());
PrintF("\n"); PrintF(out, "\n");
break; break;
case CALLBACKS: case CALLBACKS:
PrintF(" -type = call backs\n"); PrintF(out, " -type = call backs\n");
PrintF(" -callback object:\n"); PrintF(out, " -callback object:\n");
GetCallbackObject()->Print(); GetCallbackObject()->Print(out);
break; break;
case INTERCEPTOR: case INTERCEPTOR:
PrintF(" -type = lookup interceptor\n"); PrintF(out, " -type = lookup interceptor\n");
break; break;
case CONSTANT_TRANSITION: case CONSTANT_TRANSITION:
PrintF(" -type = constant property transition\n"); PrintF(out, " -type = constant property transition\n");
break; break;
case NULL_DESCRIPTOR: case NULL_DESCRIPTOR:
PrintF(" =type = null descriptor\n"); PrintF(out, " =type = null descriptor\n");
break; break;
} }
} }
void Descriptor::Print() { void Descriptor::Print(FILE* out) {
PrintF("Descriptor "); PrintF(out, "Descriptor ");
GetKey()->ShortPrint(); GetKey()->ShortPrint(out);
PrintF(" @ "); PrintF(out, " @ ");
GetValue()->ShortPrint(); GetValue()->ShortPrint(out);
PrintF(" %d\n", GetDetails().index()); PrintF(out, " %d\n", GetDetails().index());
} }

8
deps/v8/src/property.h

@ -60,8 +60,8 @@ class Descriptor BASE_EMBEDDED {
Object* GetValue() { return value_; } Object* GetValue() { return value_; }
PropertyDetails GetDetails() { return details_; } PropertyDetails GetDetails() { return details_; }
#ifdef DEBUG #ifdef OBJECT_PRINT
void Print(); void Print(FILE* out);
#endif #endif
void SetEnumerationIndex(int index) { void SetEnumerationIndex(int index) {
@ -310,8 +310,8 @@ class LookupResult BASE_EMBEDDED {
return GetValue(); return GetValue();
} }
#ifdef DEBUG #ifdef OBJECT_PRINT
void Print(); void Print(FILE* out);
#endif #endif
Object* GetValue() { Object* GetValue() {

27
deps/v8/src/regexp.js

@ -32,7 +32,7 @@ const $RegExp = global.RegExp;
// A recursive descent parser for Patterns according to the grammar of // A recursive descent parser for Patterns according to the grammar of
// ECMA-262 15.10.1, with deviations noted below. // 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. // RegExp : Called as constructor; see ECMA-262, section 15.10.4.
if (IS_REGEXP(pattern)) { if (IS_REGEXP(pattern)) {
if (!IS_UNDEFINED(flags)) { if (!IS_UNDEFINED(flags)) {
@ -80,7 +80,7 @@ function DoConstructRegExp(object, pattern, flags, isConstructorCall) {
function RegExpConstructor(pattern, flags) { function RegExpConstructor(pattern, flags) {
if (%_IsConstructCall()) { if (%_IsConstructCall()) {
DoConstructRegExp(this, pattern, flags, true); DoConstructRegExp(this, pattern, flags);
} else { } else {
// RegExp : Called as function; see ECMA-262, section 15.10.3.1. // RegExp : Called as function; see ECMA-262, section 15.10.3.1.
if (IS_REGEXP(pattern) && IS_UNDEFINED(flags)) { 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 // the empty string. For compatibility with JSC, we match their
// behavior. // behavior.
if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) { if (IS_UNDEFINED(pattern) && %_ArgumentsLength() != 0) {
DoConstructRegExp(this, 'undefined', flags, false); DoConstructRegExp(this, 'undefined', flags);
} else { } else {
DoConstructRegExp(this, pattern, flags, false); DoConstructRegExp(this, pattern, flags);
} }
} }
@ -150,12 +150,12 @@ function BuildResultFromMatchInfo(lastMatchInfo, s) {
function RegExpExecNoTests(regexp, string, start) { function RegExpExecNoTests(regexp, string, start) {
// Must be called with RegExp, string and positive integer as arguments. // Must be called with RegExp, string and positive integer as arguments.
var matchInfo = DoRegExpExec(regexp, string, start); var matchInfo = %_RegExpExec(regexp, string, start, lastMatchInfo);
var result = null;
if (matchInfo !== null) { 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) { // '?' %_StringCharCodeAt(this.source, 2) != 63) { // '?'
if (!%_ObjectEquals(regexp_key, this)) { if (!%_ObjectEquals(regexp_key, this)) {
regexp_key = this; regexp_key = this;
regexp_val = new $RegExp(this.source.substring(2, this.source.length), regexp_val = new $RegExp(SubString(this.source, 2, this.source.length),
(this.ignoreCase ? 'i' : '') (!this.ignoreCase
+ (this.multiline ? 'm' : '')); ? !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]); %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
// matchIndices is either null or the lastMatchInfo array. // matchIndices is either null or the lastMatchInfo array.

2
deps/v8/src/runtime.cc

@ -7204,7 +7204,7 @@ static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
// extension object itself. // extension object itself.
if ((attributes & READ_ONLY) == 0 || if ((attributes & READ_ONLY) == 0 ||
(context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
Handle<Object> set = SetProperty(context_ext, name, value, attributes); Handle<Object> set = SetProperty(context_ext, name, value, NONE);
if (set.is_null()) { if (set.is_null()) {
// Failure::Exception is converted to a null handle in the // Failure::Exception is converted to a null handle in the
// handle-based methods such as SetProperty. We therefore need // handle-based methods such as SetProperty. We therefore need

53
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++) { for (int i = 0; i < len; i++) {
if (array[i] != kUnusedChunkTableEntry) { if (array[i] != kUnusedChunkTableEntry) {
AtomicWord* subarray = reinterpret_cast<AtomicWord*>(array[i]); uintptr_t* subarray = reinterpret_cast<uintptr_t*>(array[i]);
if (level > 1) { if (level > 1) {
Release_Store(&array[i], kUnusedChunkTableEntry); array[i] = kUnusedChunkTableEntry;
FreeChunkTables(subarray, 1 << kChunkTableBitsPerLevel, level - 1); FreeChunkTables(subarray, 1 << kChunkTableBitsPerLevel, level - 1);
} else { } else {
Release_Store(&array[i], kUnusedChunkTableEntry); array[i] = kUnusedChunkTableEntry;
} }
delete[] subarray; delete[] subarray;
} }
@ -822,7 +822,7 @@ void MemoryAllocator::AddToAllocatedChunks(Address addr, intptr_t size) {
void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start, void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
uintptr_t chunk_index_base) { uintptr_t chunk_index_base) {
AtomicWord* fine_grained = AllocatedChunksFinder( uintptr_t* fine_grained = AllocatedChunksFinder(
chunk_table_, chunk_table_,
chunk_index_base, chunk_index_base,
kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel, kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@ -830,7 +830,7 @@ void MemoryAllocator::AddChunkUsingAddress(uintptr_t chunk_start,
int index = FineGrainedIndexForAddress(chunk_index_base); int index = FineGrainedIndexForAddress(chunk_index_base);
if (fine_grained[index] != kUnusedChunkTableEntry) index++; if (fine_grained[index] != kUnusedChunkTableEntry) index++;
ASSERT(fine_grained[index] == kUnusedChunkTableEntry); 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( void MemoryAllocator::RemoveChunkFoundUsingAddress(
uintptr_t chunk_start, uintptr_t chunk_start,
uintptr_t chunk_index_base) { uintptr_t chunk_index_base) {
AtomicWord* fine_grained = AllocatedChunksFinder( uintptr_t* fine_grained = AllocatedChunksFinder(
chunk_table_, chunk_table_,
chunk_index_base, chunk_index_base,
kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel, kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@ -854,22 +854,23 @@ void MemoryAllocator::RemoveChunkFoundUsingAddress(
ASSERT(fine_grained != kUnusedChunkTableEntry); ASSERT(fine_grained != kUnusedChunkTableEntry);
int index = FineGrainedIndexForAddress(chunk_index_base); int index = FineGrainedIndexForAddress(chunk_index_base);
ASSERT(fine_grained[index] != kUnusedChunkTableEntry); ASSERT(fine_grained[index] != kUnusedChunkTableEntry);
if (fine_grained[index] != static_cast<AtomicWord>(chunk_start)) { if (fine_grained[index] != chunk_start) {
index++; index++;
ASSERT(fine_grained[index] == static_cast<AtomicWord>(chunk_start)); ASSERT(fine_grained[index] == chunk_start);
Release_Store(&fine_grained[index], kUnusedChunkTableEntry); fine_grained[index] = kUnusedChunkTableEntry;
} else { } else {
Release_Store(&fine_grained[index], fine_grained[index + 1]); // If only one of the entries is used it must be the first, since
// Here for a moment the two entries are duplicates, but the reader can // InAllocatedChunks relies on that. Move things around so that this is
// handle that. // the case.
NoBarrier_Store(&fine_grained[index + 1], kUnusedChunkTableEntry); fine_grained[index] = fine_grained[index + 1];
fine_grained[index + 1] = kUnusedChunkTableEntry;
} }
} }
bool MemoryAllocator::InAllocatedChunks(Address addr) { bool MemoryAllocator::InAllocatedChunks(Address addr) {
uintptr_t int_address = reinterpret_cast<uintptr_t>(addr); uintptr_t int_address = reinterpret_cast<uintptr_t>(addr);
AtomicWord* fine_grained = AllocatedChunksFinder( uintptr_t* fine_grained = AllocatedChunksFinder(
chunk_table_, chunk_table_,
int_address, int_address,
kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel, kChunkSizeLog2 + (kChunkTableLevels - 1) * kChunkTableBitsPerLevel,
@ -877,21 +878,18 @@ bool MemoryAllocator::InAllocatedChunks(Address addr) {
if (fine_grained == NULL) return false; if (fine_grained == NULL) return false;
int index = FineGrainedIndexForAddress(int_address); int index = FineGrainedIndexForAddress(int_address);
if (fine_grained[index] == kUnusedChunkTableEntry) return false; if (fine_grained[index] == kUnusedChunkTableEntry) return false;
uintptr_t entry = static_cast<uintptr_t>(fine_grained[index]); uintptr_t entry = fine_grained[index];
if (entry <= int_address && entry + kChunkSize > int_address) return true; if (entry <= int_address && entry + kChunkSize > int_address) return true;
index++; index++;
if (fine_grained[index] == kUnusedChunkTableEntry) return false; if (fine_grained[index] == kUnusedChunkTableEntry) return false;
entry = static_cast<uintptr_t>(fine_grained[index]); entry = 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.
if (entry <= int_address && entry + kChunkSize > int_address) return true; if (entry <= int_address && entry + kChunkSize > int_address) return true;
return false; return false;
} }
AtomicWord* MemoryAllocator::AllocatedChunksFinder( uintptr_t* MemoryAllocator::AllocatedChunksFinder(
AtomicWord* table, uintptr_t* table,
uintptr_t address, uintptr_t address,
int bit_position, int bit_position,
CreateTables create_as_needed) { CreateTables create_as_needed) {
@ -906,8 +904,8 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
address & ((V8_INTPTR_C(1) << bit_position) - 1); address & ((V8_INTPTR_C(1) << bit_position) - 1);
ASSERT((table == chunk_table_ && index < kChunkTableTopLevelEntries) || ASSERT((table == chunk_table_ && index < kChunkTableTopLevelEntries) ||
(table != chunk_table_ && index < 1 << kChunkTableBitsPerLevel)); (table != chunk_table_ && index < 1 << kChunkTableBitsPerLevel));
AtomicWord* more_fine_grained_table = uintptr_t* more_fine_grained_table =
reinterpret_cast<AtomicWord*>(table[index]); reinterpret_cast<uintptr_t*>(table[index]);
if (more_fine_grained_table == kUnusedChunkTableEntry) { if (more_fine_grained_table == kUnusedChunkTableEntry) {
if (create_as_needed == kDontCreateTables) return NULL; if (create_as_needed == kDontCreateTables) return NULL;
int words_needed = 1 << kChunkTableBitsPerLevel; int words_needed = 1 << kChunkTableBitsPerLevel;
@ -915,12 +913,11 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
words_needed = words_needed =
(1 << kChunkTableBitsPerLevel) * kChunkTableFineGrainedWordsPerEntry; (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++) { for (int i = 0; i < words_needed; i++) {
more_fine_grained_table[i] = kUnusedChunkTableEntry; more_fine_grained_table[i] = kUnusedChunkTableEntry;
} }
Release_Store(&table[index], table[index] = reinterpret_cast<uintptr_t>(more_fine_grained_table);
reinterpret_cast<AtomicWord>(more_fine_grained_table));
} }
return AllocatedChunksFinder( return AllocatedChunksFinder(
more_fine_grained_table, more_fine_grained_table,
@ -930,7 +927,7 @@ AtomicWord* MemoryAllocator::AllocatedChunksFinder(
} }
AtomicWord MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries]; uintptr_t MemoryAllocator::chunk_table_[kChunkTableTopLevelEntries];
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

9
deps/v8/src/spaces.h

@ -28,7 +28,6 @@
#ifndef V8_SPACES_H_ #ifndef V8_SPACES_H_
#define V8_SPACES_H_ #define V8_SPACES_H_
#include "atomicops.h"
#include "list-inl.h" #include "list-inl.h"
#include "log.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 // The chunks are not chunk-size aligned so for a given chunk-sized area of
// memory there can be two chunks that cover it. // memory there can be two chunks that cover it.
static const int kChunkTableFineGrainedWordsPerEntry = 2; static const int kChunkTableFineGrainedWordsPerEntry = 2;
static const AtomicWord kUnusedChunkTableEntry = 0; static const uintptr_t kUnusedChunkTableEntry = 0;
// Maximum space size in bytes. // Maximum space size in bytes.
static intptr_t capacity_; static intptr_t capacity_;
@ -696,7 +695,7 @@ class MemoryAllocator : public AllStatic {
static intptr_t capacity_executable_; static intptr_t capacity_executable_;
// Top level table to track whether memory is part of a chunk or not. // 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. // Allocated space size in bytes.
static intptr_t size_; static intptr_t size_;
@ -766,11 +765,11 @@ class MemoryAllocator : public AllStatic {
// Controls whether the lookup creates intermediate levels of tables as // Controls whether the lookup creates intermediate levels of tables as
// needed. // needed.
enum CreateTables { kDontCreateTables, kCreateTablesAsNeeded }; enum CreateTables { kDontCreateTables, kCreateTablesAsNeeded };
static AtomicWord* AllocatedChunksFinder(AtomicWord* table, static uintptr_t* AllocatedChunksFinder(uintptr_t* table,
uintptr_t address, uintptr_t address,
int bit_position, int bit_position,
CreateTables create_as_needed); CreateTables create_as_needed);
static void FreeChunkTables(AtomicWord* array, int length, int level); static void FreeChunkTables(uintptr_t* array, int length, int level);
static int FineGrainedIndexForAddress(uintptr_t address) { static int FineGrainedIndexForAddress(uintptr_t address) {
int index = ((address >> kChunkSizeLog2) & int index = ((address >> kChunkSizeLog2) &
((1 << kChunkTableBitsPerLevel) - 1)); ((1 << kChunkTableBitsPerLevel) - 1));

6
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 // 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 // manageable chunks to avoid losing parts of the output in the OS
// printing code. This is a problem on Windows in particular; see // 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) { for (unsigned next; (next = position + 2048) < length_; position = next) {
char save = buffer_[next]; char save = buffer_[next];
buffer_[next] = '\0'; buffer_[next] = '\0';
internal::PrintF("%s", &buffer_[position]); internal::PrintF(out, "%s", &buffer_[position]);
buffer_[next] = save; buffer_[next] = save;
} }
internal::PrintF("%s", &buffer_[position]); internal::PrintF(out, "%s", &buffer_[position]);
} }

3
deps/v8/src/string-stream.h

@ -138,7 +138,8 @@ class StringStream {
FmtElm arg3); FmtElm arg3);
// Getting the message out. // Getting the message out.
void OutputToStdOut(); void OutputToFile(FILE* out);
void OutputToStdOut() { OutputToFile(stdout); }
void Log(); void Log();
Handle<String> ToString(); Handle<String> ToString();
SmartPointer<const char> ToCString() const; SmartPointer<const char> ToCString() const;

67
deps/v8/src/string.js

@ -159,7 +159,7 @@ function StringLocaleCompare(other) {
function StringMatch(regexp) { function StringMatch(regexp) {
var subject = TO_STRING_INLINE(this); var subject = TO_STRING_INLINE(this);
if (IS_REGEXP(regexp)) { 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]); %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]);
// lastMatchInfo is defined in regexp.js. // lastMatchInfo is defined in regexp.js.
return %StringMatch(subject, regexp, lastMatchInfo); 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 // Expand the $-expressions in the string and return a new string with
// the result. // the result.
function ExpandReplacement(string, subject, matchInfo, builder) { function ExpandReplacement(string, subject, matchInfo, builder) {
var length = string.length;
var builder_elements = builder.elements;
var next = %StringIndexOf(string, '$', 0); var next = %StringIndexOf(string, '$', 0);
if (next < 0) { if (next < 0) {
builder.add(string); if (length > 0) builder_elements.push(string);
return; return;
} }
// Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102.
var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match. var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match.
if (next > 0) builder.add(SubString(string, 0, next)); if (next > 0) builder_elements.push(SubString(string, 0, next));
var length = string.length;
while (true) { while (true) {
var expansion = '$'; var expansion = '$';
@ -264,7 +265,7 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
var peek = %_StringCharCodeAt(string, position); var peek = %_StringCharCodeAt(string, position);
if (peek == 36) { // $$ if (peek == 36) { // $$
++position; ++position;
builder.add('$'); builder_elements.push('$');
} else if (peek == 38) { // $& - match } else if (peek == 38) { // $& - match
++position; ++position;
builder.addSpecialSlice(matchInfo[CAPTURE0], builder.addSpecialSlice(matchInfo[CAPTURE0],
@ -301,14 +302,14 @@ function ExpandReplacement(string, subject, matchInfo, builder) {
// digit capture references, we can only enter here when a // digit capture references, we can only enter here when a
// single digit capture reference is outside the range of // single digit capture reference is outside the range of
// captures. // captures.
builder.add('$'); builder_elements.push('$');
--position; --position;
} }
} else { } else {
builder.add('$'); builder_elements.push('$');
} }
} else { } else {
builder.add('$'); builder_elements.push('$');
} }
// Go the the next $ in the string. // 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. // haven't reached the end, we need to append the suffix.
if (next < 0) { if (next < 0) {
if (position < length) { if (position < length) {
builder.add(SubString(string, position, length)); builder_elements.push(SubString(string, position, length));
} }
return; return;
} }
// Append substring between the previous and the next $ character. // 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 currentIndex = 0;
var startIndex = 0; var startIndex = 0;
var startMatch = 0;
var result = []; var result = [];
outer_loop: outer_loop:
while (true) { while (true) {
if (startIndex === length) { if (startIndex === length) {
result.push(subject.slice(currentIndex, length)); result.push(SubString(subject, currentIndex, length));
break; break;
} }
var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); var matchInfo = DoRegExpExec(separator, subject, startIndex);
if (matchInfo == null || length === (startMatch = matchInfo[CAPTURE0])) {
if (IS_NULL(matchInfo)) { result.push(SubString(subject, currentIndex, length));
result.push(subject.slice(currentIndex, length));
break; break;
} }
var endIndex = matchInfo[CAPTURE1]; var endIndex = matchInfo[CAPTURE1];
// We ignore a zero-length match at the currentIndex. // We ignore a zero-length match at the currentIndex.
@ -584,7 +586,12 @@ function StringSplit(separator, limit) {
continue; 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; if (result.length === limit) break;
var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; 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 // ECMA-262 section 15.5.4.15
function StringSubstring(start, end) { function StringSubstring(start, end) {
var s = TO_STRING_INLINE(this); var s = TO_STRING_INLINE(this);
@ -844,24 +838,21 @@ function ReplaceResultBuilder(str) {
ReplaceResultBuilder.prototype.add = function(str) { ReplaceResultBuilder.prototype.add = function(str) {
str = TO_STRING_INLINE(str); str = TO_STRING_INLINE(str);
if (str.length > 0) { if (str.length > 0) this.elements.push(str);
var elements = this.elements;
elements[elements.length] = str;
}
} }
ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) { ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
var len = end - start; var len = end - start;
if (start < 0 || len <= 0) return; if (start < 0 || len <= 0) return;
var elements = this.elements;
if (start < 0x80000 && len < 0x800) { if (start < 0x80000 && len < 0x800) {
elements[elements.length] = (start << 11) | len; this.elements.push((start << 11) | len);
} else { } else {
// 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength, // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
// so -len is a smi. // so -len is a smi.
elements[elements.length] = -len; var elements = this.elements;
elements[elements.length] = start; elements.push(-len);
elements.push(start);
} }
} }

12
deps/v8/src/utils.cc

@ -45,8 +45,16 @@ void PrintF(const char* format, ...) {
} }
void Flush() { void PrintF(FILE* out, const char* format, ...) {
fflush(stdout); va_list arguments;
va_start(arguments, format);
OS::VFPrint(out, format, arguments);
va_end(arguments);
}
void Flush(FILE* out) {
fflush(out);
} }

2
deps/v8/src/v8-counters.h

@ -28,7 +28,9 @@
#ifndef V8_V8_COUNTERS_H_ #ifndef V8_V8_COUNTERS_H_
#define V8_V8_COUNTERS_H_ #define V8_V8_COUNTERS_H_
#include "allocation.h"
#include "counters.h" #include "counters.h"
#include "v8globals.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {

10
deps/v8/src/v8utils.h

@ -43,18 +43,26 @@ namespace internal {
// so it works on MacOSX. // so it works on MacOSX.
#if defined(__MACH__) && defined(__APPLE__) #if defined(__MACH__) && defined(__APPLE__)
#define PRINTF_CHECKING #define PRINTF_CHECKING
#define FPRINTF_CHECKING
#else // MacOsX. #else // MacOsX.
#define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2))) #define PRINTF_CHECKING __attribute__ ((format (printf, 1, 2)))
#define FPRINTF_CHECKING __attribute__ ((format (printf, 2, 3)))
#endif #endif
#else #else
#define PRINTF_CHECKING #define PRINTF_CHECKING
#define FPRINTF_CHECKING
#endif #endif
// Our version of printf(). // Our version of printf().
void PRINTF_CHECKING PrintF(const char* format, ...); void PRINTF_CHECKING PrintF(const char* format, ...);
void FPRINTF_CHECKING PrintF(FILE* out, const char* format, ...);
// Our version of fflush. // 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 // Read a line of characters after printing the prompt to stdout. The resulting

4
deps/v8/src/version.cc

@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script. // cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3 #define MAJOR_VERSION 3
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_NUMBER 3 #define BUILD_NUMBER 4
#define PATCH_LEVEL 0 #define PATCH_LEVEL 1
#define CANDIDATE_VERSION false #define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the // Define SONAME to have the SCons build the put a specific SONAME into the

4
deps/v8/src/x64/codegen-x64.cc

@ -6784,9 +6784,9 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
// Check that both indices are valid. // Check that both indices are valid.
__ movq(tmp2.reg(), FieldOperand(object.reg(), JSArray::kLengthOffset)); __ movq(tmp2.reg(), FieldOperand(object.reg(), JSArray::kLengthOffset));
__ cmpl(tmp2.reg(), index1.reg()); __ SmiCompare(tmp2.reg(), index1.reg());
deferred->Branch(below_equal); deferred->Branch(below_equal);
__ cmpl(tmp2.reg(), index2.reg()); __ SmiCompare(tmp2.reg(), index2.reg());
deferred->Branch(below_equal); deferred->Branch(below_equal);
// Bring addresses into index1 and index2. // Bring addresses into index1 and index2.

64
deps/v8/test/cctest/test-heap.cc

@ -1216,7 +1216,7 @@ TEST(TestInternalWeakListsTraverseWithGC) {
TEST(TestSizeOfObjectsVsHeapIteratorPrecision) { TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
InitializeVM(); InitializeVM();
intptr_t size_of_objects_1 = Heap::SizeOfObjects(); intptr_t size_of_objects_1 = Heap::SizeOfObjects();
HeapIterator iterator(HeapIterator::kPreciseFiltering); HeapIterator iterator(HeapIterator::kFilterFreeListNodes);
intptr_t size_of_objects_2 = 0; intptr_t size_of_objects_2 = 0;
for (HeapObject* obj = iterator.next(); for (HeapObject* obj = iterator.next();
obj != NULL; obj != NULL;
@ -1240,3 +1240,65 @@ TEST(TestSizeOfObjectsVsHeapIteratorPrecision) {
CHECK_GT(size_of_objects_2 / 100, delta); CHECK_GT(size_of_objects_2 / 100, delta);
} }
} }
class HeapIteratorTestHelper {
public:
HeapIteratorTestHelper(Object* a, Object* b)
: a_(a), b_(b), a_found_(false), b_found_(false) {}
bool a_found() { return a_found_; }
bool b_found() { return b_found_; }
void IterateHeap(HeapIterator::HeapObjectsFiltering mode) {
HeapIterator iterator(mode);
for (HeapObject* obj = iterator.next();
obj != NULL;
obj = iterator.next()) {
if (obj == a_)
a_found_ = true;
else if (obj == b_)
b_found_ = true;
}
}
private:
Object* a_;
Object* b_;
bool a_found_;
bool b_found_;
};
TEST(HeapIteratorFilterUnreachable) {
InitializeVM();
v8::HandleScope scope;
CompileRun("a = {}; b = {};");
v8::Handle<Object> a(Top::context()->global()->GetProperty(
*Factory::LookupAsciiSymbol("a"))->ToObjectChecked());
v8::Handle<Object> b(Top::context()->global()->GetProperty(
*Factory::LookupAsciiSymbol("b"))->ToObjectChecked());
CHECK_NE(*a, *b);
{
HeapIteratorTestHelper helper(*a, *b);
helper.IterateHeap(HeapIterator::kFilterUnreachable);
CHECK(helper.a_found());
CHECK(helper.b_found());
}
CHECK(Top::context()->global()->DeleteProperty(
*Factory::LookupAsciiSymbol("a"), JSObject::FORCE_DELETION));
// We ensure that GC will not happen, so our raw pointer stays valid.
AssertNoAllocation no_alloc;
Object* a_saved = *a;
a.Clear();
// Verify that "a" object still resides in the heap...
{
HeapIteratorTestHelper helper(a_saved, *b);
helper.IterateHeap(HeapIterator::kNoFiltering);
CHECK(helper.a_found());
CHECK(helper.b_found());
}
// ...but is now unreachable.
{
HeapIteratorTestHelper helper(a_saved, *b);
helper.IterateHeap(HeapIterator::kFilterUnreachable);
CHECK(!helper.a_found());
CHECK(helper.b_found());
}
}

13
deps/v8/test/mjsunit/array-slice.js

@ -218,3 +218,16 @@
assertTrue(delete Array.prototype[5]); 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));
})();

17
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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
// met: // met:
@ -360,3 +360,18 @@ function TestSpecialCasesInheritedElementSort() {
} }
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);

43
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();

3
deps/v8/tools/gyp/v8.gyp

@ -70,7 +70,8 @@
'DEBUG', 'DEBUG',
'_DEBUG', '_DEBUG',
'ENABLE_DISASSEMBLER', 'ENABLE_DISASSEMBLER',
'V8_ENABLE_CHECKS' 'V8_ENABLE_CHECKS',
'OBJECT_PRINT',
], ],
'msvs_settings': { 'msvs_settings': {
'VCCLCompilerTool': { 'VCCLCompilerTool': {

3
deps/v8/tools/v8.xcodeproj/project.pbxproj

@ -1850,6 +1850,7 @@
DEBUG, DEBUG,
ENABLE_LOGGING_AND_PROFILING, ENABLE_LOGGING_AND_PROFILING,
V8_ENABLE_CHECKS, V8_ENABLE_CHECKS,
OBJECT_PRINT,
ENABLE_VMSTATE_TRACKING, ENABLE_VMSTATE_TRACKING,
); );
GCC_SYMBOLS_PRIVATE_EXTERN = YES; GCC_SYMBOLS_PRIVATE_EXTERN = YES;
@ -1914,6 +1915,7 @@
V8_TARGET_ARCH_IA32, V8_TARGET_ARCH_IA32,
DEBUG, DEBUG,
V8_ENABLE_CHECKS, V8_ENABLE_CHECKS,
OBJECT_PRINT,
ENABLE_DEBUGGER_SUPPORT, ENABLE_DEBUGGER_SUPPORT,
); );
HEADER_SEARCH_PATHS = ../src; HEADER_SEARCH_PATHS = ../src;
@ -1976,6 +1978,7 @@
V8_TARGET_ARCH_IA32, V8_TARGET_ARCH_IA32,
DEBUG, DEBUG,
V8_ENABLE_CHECKS, V8_ENABLE_CHECKS,
OBJECT_PRINT,
ENABLE_DEBUGGER_SUPPORT, ENABLE_DEBUGGER_SUPPORT,
); );
HEADER_SEARCH_PATHS = ../src; HEADER_SEARCH_PATHS = ../src;

2
deps/v8/tools/visual_studio/debug.vsprops

@ -7,7 +7,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS" PreprocessorDefinitions="DEBUG;_DEBUG;ENABLE_DISASSEMBLER;V8_ENABLE_CHECKS,OBJECT_PRINT"
RuntimeLibrary="1" RuntimeLibrary="1"
/> />
<Tool <Tool

Loading…
Cancel
Save