summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Dahl <ry@tinyclouds.org>2010-07-15 18:52:48 -0700
committerRyan Dahl <ry@tinyclouds.org>2010-07-15 18:52:48 -0700
commitdcd41ca864749b130b943c1e41eb993388f7e9d8 (patch)
tree8decfc4a73177c24c530a5428b57dcd159cfcf83
parent078a48a97b5b2597443f867e904a4c7e7f061c42 (diff)
downloadnode-new-dcd41ca864749b130b943c1e41eb993388f7e9d8.tar.gz
Upgrade V8 to 2.3.0
-rw-r--r--deps/v8/ChangeLog8
-rw-r--r--deps/v8/include/v8-debug.h16
-rw-r--r--deps/v8/src/accessors.cc4
-rw-r--r--deps/v8/src/api.cc6
-rw-r--r--deps/v8/src/arm/codegen-arm.cc183
-rw-r--r--deps/v8/src/arm/full-codegen-arm.cc9
-rw-r--r--deps/v8/src/arm/stub-cache-arm.cc7
-rw-r--r--deps/v8/src/codegen.h27
-rwxr-xr-xdeps/v8/src/compiler.cc10
-rw-r--r--deps/v8/src/contexts.cc22
-rw-r--r--deps/v8/src/debug.cc116
-rw-r--r--deps/v8/src/debug.h29
-rw-r--r--deps/v8/src/factory.cc2
-rw-r--r--deps/v8/src/factory.h2
-rw-r--r--deps/v8/src/frames.cc4
-rw-r--r--deps/v8/src/globals.h1
-rw-r--r--deps/v8/src/heap.cc11
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc8
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc6
-rw-r--r--deps/v8/src/objects-inl.h14
-rw-r--r--deps/v8/src/objects.h2
-rw-r--r--deps/v8/src/parser.cc6
-rw-r--r--deps/v8/src/profile-generator.cc7
-rw-r--r--deps/v8/src/runtime.cc53
-rw-r--r--deps/v8/src/scopeinfo.cc275
-rw-r--r--deps/v8/src/scopeinfo.h81
-rw-r--r--deps/v8/src/v8natives.js44
-rw-r--r--deps/v8/src/version.cc4
-rw-r--r--deps/v8/src/x64/codegen-x64.cc73
-rw-r--r--deps/v8/src/x64/stub-cache-x64.cc6
-rw-r--r--deps/v8/test/cctest/test-debug.cc65
-rw-r--r--deps/v8/test/es5conform/es5conform.status11
-rw-r--r--deps/v8/test/mjsunit/call-stub.js15
-rw-r--r--deps/v8/test/mjsunit/object-freeze.js19
-rw-r--r--deps/v8/test/mjsunit/object-seal.js195
-rw-r--r--deps/v8/test/mjsunit/regress/regress-r4998.js94
36 files changed, 1012 insertions, 423 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index cdadfba3a2..39bd3e1b2d 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,11 @@
+2010-07-15: Version 2.3.0
+
+ Added ES5 Object.seal and Object.isSealed.
+
+ Added debugger API for scheduling debugger commands from a
+ separate thread.
+
+
2010-07-14: Version 2.2.24
Added API for capturing stack traces for uncaught exceptions.
diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h
index c53b63462a..414fd8622a 100644
--- a/deps/v8/include/v8-debug.h
+++ b/deps/v8/include/v8-debug.h
@@ -76,7 +76,8 @@ enum DebugEvent {
NewFunction = 3,
BeforeCompile = 4,
AfterCompile = 5,
- ScriptCollected = 6
+ ScriptCollected = 6,
+ BreakForCommand = 7
};
@@ -172,6 +173,13 @@ class EXPORT Debug {
*/
virtual Handle<Value> GetCallbackData() const = 0;
+ /**
+ * Client data passed to DebugBreakForCommand function. The
+ * debugger takes ownership of the data and will delete it even if
+ * there is no message handler.
+ */
+ virtual ClientData* GetClientData() const = 0;
+
virtual ~EventDetails() {}
};
@@ -248,6 +256,12 @@ class EXPORT Debug {
// Break execution of JavaScript.
static void DebugBreak();
+ // Break execution of JavaScript (this method can be invoked from a
+ // non-VM thread) for further client command execution on a VM
+ // thread. Client data is then passed in EventDetails to
+ // EventCallback at the moment when the VM actually stops.
+ static void DebugBreakForCommand(ClientData* data = NULL);
+
// Message based interface. The message protocol is JSON. NOTE the message
// handler thread is not supported any more parameter must be false.
static void SetMessageHandler(MessageHandler handler,
diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc
index 9fbfe56dae..ed0bbd7a1c 100644
--- a/deps/v8/src/accessors.cc
+++ b/deps/v8/src/accessors.cc
@@ -549,8 +549,8 @@ Object* Accessors::FunctionGetArguments(Object* object, void*) {
if (frame->function() != *function) continue;
// If there is an arguments variable in the stack, we return that.
- int index = ScopeInfo<>::StackSlotIndex(function->shared()->scope_info(),
- Heap::arguments_symbol());
+ int index = function->shared()->scope_info()->
+ StackSlotIndex(Heap::arguments_symbol());
if (index >= 0) {
Handle<Object> arguments = Handle<Object>(frame->GetExpression(index));
if (!arguments->IsTheHole()) return *arguments;
diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc
index 07d9eb0ac7..b3c77d8cdd 100644
--- a/deps/v8/src/api.cc
+++ b/deps/v8/src/api.cc
@@ -4213,6 +4213,12 @@ void Debug::DebugBreak() {
}
+void Debug::DebugBreakForCommand(ClientData* data) {
+ if (!i::V8::IsRunning()) return;
+ i::Debugger::EnqueueDebugCommand(data);
+}
+
+
static v8::Debug::MessageHandler message_handler = NULL;
static void MessageHandlerWrapper(const v8::Debug::Message& message) {
diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index 6e0604bc6e..71775ac971 100644
--- a/deps/v8/src/arm/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -54,11 +54,15 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
Condition cc,
bool never_nan_nan);
static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* lhs_not_nan,
Label* slow,
bool strict);
static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc);
-static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm);
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+ Register lhs,
+ Register rhs);
static void MultiplyByKnownInt(MacroAssembler* masm,
Register source,
Register destination,
@@ -1404,11 +1408,7 @@ void CodeGenerator::Comparison(Condition cc,
// Perform non-smi comparison by stub.
// CompareStub takes arguments in r0 and r1, returns <0, >0 or 0 in r0.
// We call with 0 args because there are 0 on the stack.
- if (!rhs.is(r0)) {
- __ Swap(rhs, lhs, ip);
- }
-
- CompareStub stub(cc, strict);
+ CompareStub stub(cc, strict, kBothCouldBeNaN, true, lhs, rhs);
frame_->CallStub(&stub, 0);
__ cmp(r0, Operand(0));
exit.Jump();
@@ -6968,7 +6968,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
// undefined >= undefined should fail.
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
}
}
@@ -6982,7 +6982,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
} else {
__ mov(r0, Operand(EQUAL)); // Things are <=, >=, ==, === themselves.
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
if (cc != eq || !never_nan_nan) {
// For less and greater we don't have to check for NaN since the result of
@@ -7014,14 +7014,14 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
// value if it's a NaN.
if (cc != eq) {
// All-zero means Infinity means equal.
- __ mov(pc, Operand(lr), LeaveCC, eq); // Return equal
+ __ Ret(eq);
if (cc == le) {
__ mov(r0, Operand(GREATER)); // NaN <= NaN should fail.
} else {
__ mov(r0, Operand(LESS)); // NaN >= NaN should fail.
}
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
// No fall through here.
}
@@ -7032,43 +7032,50 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm,
// See comment at call site.
static void EmitSmiNonsmiComparison(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* lhs_not_nan,
Label* slow,
bool strict) {
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
Label rhs_is_smi;
- __ tst(r0, Operand(kSmiTagMask));
+ __ tst(rhs, Operand(kSmiTagMask));
__ b(eq, &rhs_is_smi);
// Lhs is a Smi. Check whether the rhs is a heap number.
- __ CompareObjectType(r0, r4, r4, HEAP_NUMBER_TYPE);
+ __ CompareObjectType(rhs, r4, r4, HEAP_NUMBER_TYPE);
if (strict) {
// If rhs is not a number and lhs is a Smi then strict equality cannot
- // succeed. Return non-equal (r0 is already not zero)
- __ mov(pc, Operand(lr), LeaveCC, ne); // Return.
+ // succeed. Return non-equal
+ // If rhs is r0 then there is already a non zero value in it.
+ if (!rhs.is(r0)) {
+ __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
+ }
+ __ Ret(ne);
} else {
// Smi compared non-strictly with a non-Smi non-heap-number. Call
// the runtime.
__ b(ne, slow);
}
- // Lhs (r1) is a smi, rhs (r0) is a number.
+ // Lhs is a smi, rhs is a number.
if (CpuFeatures::IsSupported(VFP3)) {
- // Convert lhs to a double in d7 .
+ // Convert lhs to a double in d7.
CpuFeatures::Scope scope(VFP3);
- __ mov(r7, Operand(r1, ASR, kSmiTagSize));
- __ vmov(s15, r7);
- __ vcvt_f64_s32(d7, s15);
+ __ SmiToDoubleVFPRegister(lhs, d7, r7, s15);
// Load the double from rhs, tagged HeapNumber r0, to d6.
- __ sub(r7, r0, Operand(kHeapObjectTag));
+ __ sub(r7, rhs, Operand(kHeapObjectTag));
__ vldr(d6, r7, HeapNumber::kValueOffset);
} else {
__ push(lr);
// Convert lhs to a double in r2, r3.
- __ mov(r7, Operand(r1));
+ __ mov(r7, Operand(lhs));
ConvertToDoubleStub stub1(r3, r2, r7, r6);
__ Call(stub1.GetCode(), RelocInfo::CODE_TARGET);
// Load rhs to a double in r0, r1.
- __ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
+ __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
__ pop(lr);
}
@@ -7078,34 +7085,35 @@ static void EmitSmiNonsmiComparison(MacroAssembler* masm,
__ bind(&rhs_is_smi);
// Rhs is a smi. Check whether the non-smi lhs is a heap number.
- __ CompareObjectType(r1, r4, r4, HEAP_NUMBER_TYPE);
+ __ CompareObjectType(lhs, r4, r4, HEAP_NUMBER_TYPE);
if (strict) {
// If lhs is not a number and rhs is a smi then strict equality cannot
// succeed. Return non-equal.
- __ mov(r0, Operand(1), LeaveCC, ne); // Non-zero indicates not equal.
- __ mov(pc, Operand(lr), LeaveCC, ne); // Return.
+ // If lhs is r0 then there is already a non zero value in it.
+ if (!lhs.is(r0)) {
+ __ mov(r0, Operand(NOT_EQUAL), LeaveCC, ne);
+ }
+ __ Ret(ne);
} else {
// Smi compared non-strictly with a non-smi non-heap-number. Call
// the runtime.
__ b(ne, slow);
}
- // Rhs (r0) is a smi, lhs (r1) is a heap number.
+ // Rhs is a smi, lhs is a heap number.
if (CpuFeatures::IsSupported(VFP3)) {
- // Convert rhs to a double in d6 .
CpuFeatures::Scope scope(VFP3);
// Load the double from lhs, tagged HeapNumber r1, to d7.
- __ sub(r7, r1, Operand(kHeapObjectTag));
+ __ sub(r7, lhs, Operand(kHeapObjectTag));
__ vldr(d7, r7, HeapNumber::kValueOffset);
- __ mov(r7, Operand(r0, ASR, kSmiTagSize));
- __ vmov(s13, r7);
- __ vcvt_f64_s32(d6, s13);
+ // Convert rhs to a double in d6 .
+ __ SmiToDoubleVFPRegister(rhs, d6, r7, s13);
} else {
__ push(lr);
// Load lhs to a double in r2, r3.
- __ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
+ __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
// Convert rhs to a double in r0, r1.
- __ mov(r7, Operand(r0));
+ __ mov(r7, Operand(rhs));
ConvertToDoubleStub stub2(r1, r0, r7, r6);
__ Call(stub2.GetCode(), RelocInfo::CODE_TARGET);
__ pop(lr);
@@ -7159,7 +7167,7 @@ void EmitNanCheck(MacroAssembler* masm, Label* lhs_not_nan, Condition cc) {
} else {
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
__ bind(&neither_is_nan);
}
@@ -7180,11 +7188,11 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
__ cmp(rhs_mantissa, Operand(lhs_mantissa));
__ orr(r0, rhs_mantissa, Operand(lhs_mantissa), LeaveCC, ne);
// Return non-zero if the numbers are unequal.
- __ mov(pc, Operand(lr), LeaveCC, ne);
+ __ Ret(ne);
__ sub(r0, rhs_exponent, Operand(lhs_exponent), SetCC);
// If exponents are equal then return 0.
- __ mov(pc, Operand(lr), LeaveCC, eq);
+ __ Ret(eq);
// Exponents are unequal. The only way we can return that the numbers
// are equal is if one is -0 and the other is 0. We already dealt
@@ -7194,11 +7202,11 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
// equal.
__ orr(r4, lhs_mantissa, Operand(lhs_exponent, LSL, kSmiTagSize), SetCC);
__ mov(r0, Operand(r4), LeaveCC, ne);
- __ mov(pc, Operand(lr), LeaveCC, ne); // Return conditionally.
+ __ Ret(ne);
// Now they are equal if and only if the lhs exponent is zero in its
// low 31 bits.
__ mov(r0, Operand(rhs_exponent, LSL, kSmiTagSize));
- __ mov(pc, Operand(lr));
+ __ Ret();
} else {
// Call a native function to do a comparison between two non-NaNs.
// Call C routine that may not cause GC or other trouble.
@@ -7211,7 +7219,12 @@ static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc) {
// See comment at call site.
-static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm) {
+static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm,
+ Register lhs,
+ Register rhs) {
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
// If either operand is a JSObject or an oddball value, then they are
// not equal since their pointers are different.
// There is no test for undetectability in strict equality.
@@ -7219,20 +7232,20 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm) {
Label first_non_object;
// Get the type of the first operand into r2 and compare it with
// FIRST_JS_OBJECT_TYPE.
- __ CompareObjectType(r0, r2, r2, FIRST_JS_OBJECT_TYPE);
+ __ CompareObjectType(rhs, r2, r2, FIRST_JS_OBJECT_TYPE);
__ b(lt, &first_non_object);
// Return non-zero (r0 is not zero)
Label return_not_equal;
__ bind(&return_not_equal);
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
__ bind(&first_non_object);
// Check for oddballs: true, false, null, undefined.
__ cmp(r2, Operand(ODDBALL_TYPE));
__ b(eq, &return_not_equal);
- __ CompareObjectType(r1, r3, r3, FIRST_JS_OBJECT_TYPE);
+ __ CompareObjectType(lhs, r3, r3, FIRST_JS_OBJECT_TYPE);
__ b(ge, &return_not_equal);
// Check for oddballs: true, false, null, undefined.
@@ -7251,12 +7264,17 @@ static void EmitStrictTwoHeapObjectCompare(MacroAssembler* masm) {
// See comment at call site.
static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* both_loaded_as_doubles,
Label* not_heap_numbers,
Label* slow) {
- __ CompareObjectType(r0, r3, r2, HEAP_NUMBER_TYPE);
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
+ __ CompareObjectType(rhs, r3, r2, HEAP_NUMBER_TYPE);
__ b(ne, not_heap_numbers);
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
+ __ ldr(r2, FieldMemOperand(lhs, HeapObject::kMapOffset));
__ cmp(r2, r3);
__ b(ne, slow); // First was a heap number, second wasn't. Go slow case.
@@ -7264,13 +7282,13 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
// for that.
if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(VFP3);
- __ sub(r7, r0, Operand(kHeapObjectTag));
+ __ sub(r7, rhs, Operand(kHeapObjectTag));
__ vldr(d6, r7, HeapNumber::kValueOffset);
- __ sub(r7, r1, Operand(kHeapObjectTag));
+ __ sub(r7, lhs, Operand(kHeapObjectTag));
__ vldr(d7, r7, HeapNumber::kValueOffset);
} else {
- __ Ldrd(r2, r3, FieldMemOperand(r1, HeapNumber::kValueOffset));
- __ Ldrd(r0, r1, FieldMemOperand(r0, HeapNumber::kValueOffset));
+ __ Ldrd(r2, r3, FieldMemOperand(lhs, HeapNumber::kValueOffset));
+ __ Ldrd(r0, r1, FieldMemOperand(rhs, HeapNumber::kValueOffset));
}
__ jmp(both_loaded_as_doubles);
}
@@ -7278,9 +7296,14 @@ static void EmitCheckForTwoHeapNumbers(MacroAssembler* masm,
// Fast negative check for symbol-to-symbol equality.
static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
+ Register lhs,
+ Register rhs,
Label* possible_strings,
Label* not_both_strings) {
- // r2 is object type of r0.
+ ASSERT((lhs.is(r0) && rhs.is(r1)) ||
+ (lhs.is(r1) && rhs.is(r0)));
+
+ // r2 is object type of rhs.
// Ensure that no non-strings have the symbol bit set.
Label object_test;
ASSERT(kSymbolTag != 0);
@@ -7288,31 +7311,31 @@ static void EmitCheckForSymbolsOrObjects(MacroAssembler* masm,
__ b(ne, &object_test);
__ tst(r2, Operand(kIsSymbolMask));
__ b(eq, possible_strings);
- __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
+ __ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
__ b(ge, not_both_strings);
__ tst(r3, Operand(kIsSymbolMask));
__ b(eq, possible_strings);
// Both are symbols. We already checked they weren't the same pointer
// so they are not equal.
- __ mov(r0, Operand(1)); // Non-zero indicates not equal.
- __ mov(pc, Operand(lr)); // Return.
+ __ mov(r0, Operand(NOT_EQUAL));
+ __ Ret();
__ bind(&object_test);
__ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
__ b(lt, not_both_strings);
- __ CompareObjectType(r1, r2, r3, FIRST_JS_OBJECT_TYPE);
+ __ CompareObjectType(lhs, r2, r3, FIRST_JS_OBJECT_TYPE);
__ b(lt, not_both_strings);
- // If both objects are undetectable, they are equal. Otherwise, they
+ // If both objects are undetectable, they are equal. Otherwise, they
// are not equal, since they are different objects and an object is not
// equal to undefined.
- __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldr(r3, FieldMemOperand(rhs, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r2, Map::kBitFieldOffset));
__ ldrb(r3, FieldMemOperand(r3, Map::kBitFieldOffset));
__ and_(r0, r2, Operand(r3));
__ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
__ eor(r0, r0, Operand(1 << Map::kIsUndetectable));
- __ mov(pc, Operand(lr)); // Return.
+ __ Ret();
}
@@ -7434,10 +7457,13 @@ void RecordWriteStub::Generate(MacroAssembler* masm) {
}
-// On entry r0 (rhs) and r1 (lhs) are the values to be compared.
+// On entry lhs_ and rhs_ are the values to be compared.
// On exit r0 is 0, positive or negative to indicate the result of
// the comparison.
void CompareStub::Generate(MacroAssembler* masm) {
+ ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+ (lhs_.is(r1) && rhs_.is(r0)));
+
Label slow; // Call builtin.
Label not_smis, both_loaded_as_doubles, lhs_not_nan;
@@ -7452,7 +7478,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
// be strictly equal if the other is a HeapNumber.
ASSERT_EQ(0, kSmiTag);
ASSERT_EQ(0, Smi::FromInt(0));
- __ and_(r2, r0, Operand(r1));
+ __ and_(r2, lhs_, Operand(rhs_));
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &not_smis);
// One operand is a smi. EmitSmiNonsmiComparison generates code that can:
@@ -7464,7 +7490,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
// comparison. If VFP3 is supported the double values of the numbers have
// been loaded into d7 and d6. Otherwise, the double values have been loaded
// into r0, r1, r2, and r3.
- EmitSmiNonsmiComparison(masm, &lhs_not_nan, &slow, strict_);
+ EmitSmiNonsmiComparison(masm, lhs_, rhs_, &lhs_not_nan, &slow, strict_);
__ bind(&both_loaded_as_doubles);
// The arguments have been converted to doubles and stored in d6 and d7, if
@@ -7481,7 +7507,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ mov(r0, Operand(EQUAL), LeaveCC, eq);
__ mov(r0, Operand(LESS), LeaveCC, lt);
__ mov(r0, Operand(GREATER), LeaveCC, gt);
- __ mov(pc, Operand(lr));
+ __ Ret();
__ bind(&nan);
// If one of the sides was a NaN then the v flag is set. Load r0 with
@@ -7492,7 +7518,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
} else {
__ mov(r0, Operand(LESS));
}
- __ mov(pc, Operand(lr));
+ __ Ret();
} else {
// Checks for NaN in the doubles we have loaded. Can return the answer or
// fall through if neither is a NaN. Also binds lhs_not_nan.
@@ -7504,11 +7530,11 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ bind(&not_smis);
// At this point we know we are dealing with two different objects,
- // and neither of them is a Smi. The objects are in r0 and r1.
+ // and neither of them is a Smi. The objects are in rhs_ and lhs_.
if (strict_) {
// This returns non-equal for some object types, or falls through if it
// was not lucky.
- EmitStrictTwoHeapObjectCompare(masm);
+ EmitStrictTwoHeapObjectCompare(masm, lhs_, rhs_);
}
Label check_for_symbols;
@@ -7516,8 +7542,10 @@ void CompareStub::Generate(MacroAssembler* masm) {
// Check for heap-number-heap-number comparison. Can jump to slow case,
// or load both doubles into r0, r1, r2, r3 and jump to the code that handles
// that case. If the inputs are not doubles then jumps to check_for_symbols.
- // In this case r2 will contain the type of r0. Never falls through.
+ // In this case r2 will contain the type of rhs_. Never falls through.
EmitCheckForTwoHeapNumbers(masm,
+ lhs_,
+ rhs_,
&both_loaded_as_doubles,
&check_for_symbols,
&flat_string_check);
@@ -7528,20 +7556,20 @@ void CompareStub::Generate(MacroAssembler* masm) {
if (cc_ == eq && !strict_) {
// Returns an answer for two symbols or two detectable objects.
// Otherwise jumps to string case or not both strings case.
- // Assumes that r2 is the type of r0 on entry.
- EmitCheckForSymbolsOrObjects(masm, &flat_string_check, &slow);
+ // Assumes that r2 is the type of rhs_ on entry.
+ EmitCheckForSymbolsOrObjects(masm, lhs_, rhs_, &flat_string_check, &slow);
}
// Check for both being sequential ASCII strings, and inline if that is the
// case.
__ bind(&flat_string_check);
- __ JumpIfNonSmisNotBothSequentialAsciiStrings(r0, r1, r2, r3, &slow);
+ __ JumpIfNonSmisNotBothSequentialAsciiStrings(lhs_, rhs_, r2, r3, &slow);
__ IncrementCounter(&Counters::string_compare_native, 1, r2, r3);
StringCompareStub::GenerateCompareFlatAsciiStrings(masm,
- r1,
- r0,
+ lhs_,
+ rhs_,
r2,
r3,
r4,
@@ -7550,7 +7578,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ bind(&slow);
- __ Push(r1, r0);
+ __ Push(lhs_, rhs_);
// Figure out which native to call and setup the arguments.
Builtins::JavaScript native;
if (cc_ == eq) {
@@ -10051,6 +10079,9 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
const char* CompareStub::GetName() {
+ ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+ (lhs_.is(r1) && rhs_.is(r0)));
+
if (name_ != NULL) return name_;
const int kMaxNameLength = 100;
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
@@ -10067,6 +10098,9 @@ const char* CompareStub::GetName() {
default: cc_name = "UnknownCondition"; break;
}
+ const char* lhs_name = lhs_.is(r0) ? "_r0" : "_r1";
+ const char* rhs_name = rhs_.is(r0) ? "_r0" : "_r1";
+
const char* strict_name = "";
if (strict_ && (cc_ == eq || cc_ == ne)) {
strict_name = "_STRICT";
@@ -10083,8 +10117,10 @@ const char* CompareStub::GetName() {
}
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
- "CompareStub_%s%s%s%s",
+ "CompareStub_%s%s%s%s%s%s",
cc_name,
+ lhs_name,
+ rhs_name,
strict_name,
never_nan_nan_name,
include_number_compare_name);
@@ -10096,8 +10132,11 @@ int CompareStub::MinorKey() {
// Encode the three parameters in a unique 16 bit value. To avoid duplicate
// stubs the never NaN NaN condition is only taken into account if the
// condition is equals.
- ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 13));
+ ASSERT((static_cast<unsigned>(cc_) >> 28) < (1 << 12));
+ ASSERT((lhs_.is(r0) && rhs_.is(r1)) ||
+ (lhs_.is(r1) && rhs_.is(r0)));
return ConditionField::encode(static_cast<unsigned>(cc_) >> 28)
+ | RegisterField::encode(lhs_.is(r0))
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == eq ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_);
diff --git a/deps/v8/src/arm/full-codegen-arm.cc b/deps/v8/src/arm/full-codegen-arm.cc
index 3fb946aa65..ec8f0f4d87 100644
--- a/deps/v8/src/arm/full-codegen-arm.cc
+++ b/deps/v8/src/arm/full-codegen-arm.cc
@@ -822,8 +822,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// the smi vs. smi case to be handled before it is called.
Label slow_case;
__ ldr(r1, MemOperand(sp, 0)); // Switch value.
- __ mov(r2, r1);
- __ orr(r2, r2, r0);
+ __ orr(r2, r1, r0);
__ tst(r2, Operand(kSmiTagMask));
__ b(ne, &slow_case);
__ cmp(r1, r0);
@@ -832,9 +831,9 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
__ b(clause->body_target()->entry_label());
__ bind(&slow_case);
- CompareStub stub(eq, true);
+ CompareStub stub(eq, true, kBothCouldBeNaN, true, r1, r0);
__ CallStub(&stub);
- __ tst(r0, r0);
+ __ cmp(r0, Operand(0));
__ b(ne, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ b(clause->body_target()->entry_label());
@@ -3088,7 +3087,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
__ jmp(if_false);
__ bind(&slow_case);
- CompareStub stub(cc, strict);
+ CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0);
__ CallStub(&stub);
__ cmp(r0, Operand(0));
__ b(cc, if_true);
diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc
index a0b6bdb413..ff3007c444 100644
--- a/deps/v8/src/arm/stub-cache-arm.cc
+++ b/deps/v8/src/arm/stub-cache-arm.cc
@@ -176,6 +176,13 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
__ cmp(entity_name, Operand(Handle<String>(name)));
__ b(eq, miss_label);
+ // Check if the entry name is not a symbol.
+ __ ldr(entity_name, FieldMemOperand(entity_name, HeapObject::kMapOffset));
+ __ ldrb(entity_name,
+ FieldMemOperand(entity_name, Map::kInstanceTypeOffset));
+ __ tst(entity_name, Operand(kIsSymbolMask));
+ __ b(eq, miss_label);
+
// Restore the properties.
__ ldr(properties,
FieldMemOperand(receiver, JSObject::kPropertiesOffset));
diff --git a/deps/v8/src/codegen.h b/deps/v8/src/codegen.h
index 783bef00d1..74855fd5a3 100644
--- a/deps/v8/src/codegen.h
+++ b/deps/v8/src/codegen.h
@@ -461,11 +461,15 @@ class CompareStub: public CodeStub {
CompareStub(Condition cc,
bool strict,
NaNInformation nan_info = kBothCouldBeNaN,
- bool include_number_compare = true) :
+ bool include_number_compare = true,
+ Register lhs = no_reg,
+ Register rhs = no_reg) :
cc_(cc),
strict_(strict),
never_nan_nan_(nan_info == kCantBothBeNaN),
include_number_compare_(include_number_compare),
+ lhs_(lhs),
+ rhs_(rhs),
name_(NULL) { }
void Generate(MacroAssembler* masm);
@@ -483,12 +487,19 @@ class CompareStub: public CodeStub {
// comparison code is used when the number comparison has been inlined, and
// the stub will be called if one of the operands is not a number.
bool include_number_compare_;
-
- // Encoding of the minor key CCCCCCCCCCCCCCNS.
+ // Register holding the left hand side of the comparison if the stub gives
+ // a choice, no_reg otherwise.
+ Register lhs_;
+ // Register holding the right hand side of the comparison if the stub gives
+ // a choice, no_reg otherwise.
+ Register rhs_;
+
+ // Encoding of the minor key CCCCCCCCCCCCRCNS.
class StrictField: public BitField<bool, 0, 1> {};
class NeverNanNanField: public BitField<bool, 1, 1> {};
class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
- class ConditionField: public BitField<int, 3, 13> {};
+ class RegisterField: public BitField<bool, 3, 1> {};
+ class ConditionField: public BitField<int, 4, 12> {};
Major MajorKey() { return Compare; }
@@ -507,11 +518,17 @@ class CompareStub: public CodeStub {
#ifdef DEBUG
void Print() {
PrintF("CompareStub (cc %d), (strict %s), "
- "(never_nan_nan %s), (number_compare %s)\n",
+ "(never_nan_nan %s), (number_compare %s) ",
static_cast<int>(cc_),
strict_ ? "true" : "false",
never_nan_nan_ ? "true" : "false",
include_number_compare_ ? "included" : "not included");
+
+ if (!lhs_.is(no_reg) && !rhs_.is(no_reg)) {
+ PrintF("(lhs r%d), (rhs r%d)\n", lhs_.code(), rhs_.code());
+ } else {
+ PrintF("\n");
+ }
}
#endif
};
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index ec6b5ffb4a..0d1fe9952b 100755
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -160,7 +160,7 @@ Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
Handle<Code> code = MakeCode(context, info);
if (!info->shared_info().is_null()) {
info->shared_info()->set_scope_info(
- *ScopeInfo<>::CreateHeapObject(info->scope()));
+ *SerializedScopeInfo::Create(info->scope()));
}
return code;
}
@@ -262,7 +262,7 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(bool is_global,
lit->name(),
lit->materialized_literal_count(),
code,
- ScopeInfo<>::CreateHeapObject(info.scope()));
+ SerializedScopeInfo::Create(info.scope()));
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
Compiler::SetFunctionInfo(result, lit, true, script);
@@ -450,7 +450,7 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
// Update the shared function info with the compiled code and the scope info.
shared->set_code(*code);
- shared->set_scope_info(*ScopeInfo<>::CreateHeapObject(info->scope()));
+ shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
// Set the expected number of properties for instances.
SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count());
@@ -485,7 +485,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
bool allow_lazy = literal->AllowsLazyCompilation() &&
!LiveEditFunctionTracker::IsActive();
- Handle<Object> scope_info(ScopeInfo<>::EmptyHeapObject());
+ Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
// Generate code
Handle<Code> code;
@@ -568,7 +568,7 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
literal->start_position(),
script,
code);
- scope_info = ScopeInfo<>::CreateHeapObject(info.scope());
+ scope_info = SerializedScopeInfo::Create(info.scope());
}
// Create a shared function info object.
diff --git a/deps/v8/src/contexts.cc b/deps/v8/src/contexts.cc
index 1eab24c28e..723354fc84 100644
--- a/deps/v8/src/contexts.cc
+++ b/deps/v8/src/contexts.cc
@@ -120,9 +120,10 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
// we have context-local slots
// check non-parameter locals in context
- Handle<Object> scope_info(context->closure()->shared()->scope_info());
+ Handle<SerializedScopeInfo> scope_info(
+ context->closure()->shared()->scope_info());
Variable::Mode mode;
- int index = ScopeInfo<>::ContextSlotIndex(*scope_info, *name, &mode);
+ int index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (index >= 0) {
// slot found
@@ -150,13 +151,11 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
}
// check parameter locals in context
- int param_index = ScopeInfo<>::ParameterIndex(*scope_info, *name);
+ int param_index = scope_info->ParameterIndex(*name);
if (param_index >= 0) {
// slot found.
int index =
- ScopeInfo<>::ContextSlotIndex(*scope_info,
- Heap::arguments_shadow_symbol(),
- NULL);
+ scope_info->ContextSlotIndex(Heap::arguments_shadow_symbol(), NULL);
ASSERT(index >= 0); // arguments must exist and be in the heap context
Handle<JSObject> arguments(JSObject::cast(context->get(index)));
ASSERT(arguments->HasLocalProperty(Heap::length_symbol()));
@@ -170,7 +169,7 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags,
// check intermediate context (holding only the function name variable)
if (follow_context_chain) {
- int index = ScopeInfo<>::FunctionContextSlotIndex(*scope_info, *name);
+ int index = scope_info->FunctionContextSlotIndex(*name);
if (index >= 0) {
// slot found
if (FLAG_trace_contexts) {
@@ -216,18 +215,19 @@ bool Context::GlobalIfNotShadowedByEval(Handle<String> name) {
ASSERT(context->is_function_context());
// Check non-parameter locals.
- Handle<Object> scope_info(context->closure()->shared()->scope_info());
+ Handle<SerializedScopeInfo> scope_info(
+ context->closure()->shared()->scope_info());
Variable::Mode mode;
- int index = ScopeInfo<>::ContextSlotIndex(*scope_info, *name, &mode);
+ int index = scope_info->ContextSlotIndex(*name, &mode);
ASSERT(index < 0 || index >= MIN_CONTEXT_SLOTS);
if (index >= 0) return false;
// Check parameter locals.
- int param_index = ScopeInfo<>::ParameterIndex(*scope_info, *name);
+ int param_index = scope_info->ParameterIndex(*name);
if (param_index >= 0) return false;
// Check context only holding the function name variable.
- index = ScopeInfo<>::FunctionContextSlotIndex(*scope_info, *name);
+ index = scope_info->FunctionContextSlotIndex(*name);
if (index >= 0) return false;
context = Context::cast(context->closure()->context());
}
diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc
index 4922a62860..728813514c 100644
--- a/deps/v8/src/debug.cc
+++ b/deps/v8/src/debug.cc
@@ -1882,6 +1882,7 @@ int Debugger::host_dispatch_micros_ = 100 * 1000;
DebuggerAgent* Debugger::agent_ = NULL;
LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
+LockingCommandMessageQueue Debugger::event_command_queue_(kQueueInitialSize);
Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
@@ -2207,39 +2208,75 @@ void Debugger::ProcessDebugEvent(v8::DebugEvent event,
event_data,
auto_continue);
}
- // Notify registered debug event listener. This can be either a C or a
- // JavaScript function.
- if (!event_listener_.is_null()) {
- if (event_listener_->IsProxy()) {
- // C debug event listener.
- Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
- v8::Debug::EventCallback2 callback =
- FUNCTION_CAST<v8::Debug::EventCallback2>(callback_obj->proxy());
- EventDetailsImpl event_details(
- event,
- Handle<JSObject>::cast(exec_state),
- event_data,
- event_listener_data_);
- callback(event_details);
- } else {
- // JavaScript debug event listener.
- ASSERT(event_listener_->IsJSFunction());
- Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
-
- // Invoke the JavaScript debug event listener.
- const int argc = 4;
- Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
- exec_state.location(),
- Handle<Object>::cast(event_data).location(),
- event_listener_data_.location() };
- Handle<Object> result = Execution::TryCall(fun, Top::global(),
- argc, argv, &caught_exception);
- // Silently ignore exceptions from debug event listeners.
+ // Notify registered debug event listener. This can be either a C or
+ // a JavaScript function. Don't call event listener for v8::Break
+ // here, if it's only a debug command -- they will be processed later.
+ if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
+ CallEventCallback(event, exec_state, event_data, NULL);
+ }
+ // Process pending debug commands.
+ if (event == v8::Break) {
+ while (!event_command_queue_.IsEmpty()) {
+ CommandMessage command = event_command_queue_.Get();
+ if (!event_listener_.is_null()) {
+ CallEventCallback(v8::BreakForCommand,
+ exec_state,
+ event_data,
+ command.client_data());
+ }
+ command.Dispose();
}
}
}
+void Debugger::CallEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ v8::Debug::ClientData* client_data) {
+ if (event_listener_->IsProxy()) {
+ CallCEventCallback(event, exec_state, event_data, client_data);
+ } else {
+ CallJSEventCallback(event, exec_state, event_data);
+ }
+}
+
+
+void Debugger::CallCEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ v8::Debug::ClientData* client_data) {
+ Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
+ v8::Debug::EventCallback2 callback =
+ FUNCTION_CAST<v8::Debug::EventCallback2>(callback_obj->proxy());
+ EventDetailsImpl event_details(
+ event,
+ Handle<JSObject>::cast(exec_state),
+ Handle<JSObject>::cast(event_data),
+ event_listener_data_,
+ client_data);
+ callback(event_details);
+}
+
+
+void Debugger::CallJSEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data) {
+ ASSERT(event_listener_->IsJSFunction());
+ Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
+
+ // Invoke the JavaScript debug event listener.
+ const int argc = 4;
+ Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
+ exec_state.location(),
+ Handle<Object>::cast(event_data).location(),
+ event_listener_data_.location() };
+ bool caught_exception = false;
+ Execution::TryCall(fun, Top::global(), argc, argv, &caught_exception);
+ // Silently ignore exceptions from debug event listeners.
+}
+
+
Handle<Context> Debugger::GetDebugContext() {
never_unload_debugger_ = true;
EnterDebugger debugger;
@@ -2273,6 +2310,7 @@ void Debugger::NotifyMessageHandler(v8::DebugEvent event,
bool sendEventMessage = false;
switch (event) {
case v8::Break:
+ case v8::BreakForCommand:
sendEventMessage = !auto_continue;
break;
case v8::Exception:
@@ -2560,6 +2598,17 @@ bool Debugger::HasCommands() {
}
+void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
+ CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
+ event_command_queue_.Put(message);
+
+ // Set the debug command break flag to have the command processed.
+ if (!Debug::InDebugger()) {
+ StackGuard::DebugCommand();
+ }
+}
+
+
bool Debugger::IsDebuggerActive() {
ScopedLock with(debugger_access_);
@@ -2761,11 +2810,13 @@ v8::Debug::ClientData* MessageImpl::GetClientData() const {
EventDetailsImpl::EventDetailsImpl(DebugEvent event,
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
- Handle<Object> callback_data)
+ Handle<Object> callback_data,
+ v8::Debug::ClientData* client_data)
: event_(event),
exec_state_(exec_state),
event_data_(event_data),
- callback_data_(callback_data) {}
+ callback_data_(callback_data),
+ client_data_(client_data) {}
DebugEvent EventDetailsImpl::GetEvent() const {
@@ -2793,6 +2844,11 @@ v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
}
+v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
+ return client_data_;
+}
+
+
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
client_data_(NULL) {
}
diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h
index fb9269272f..7bb4a428f2 100644
--- a/deps/v8/src/debug.h
+++ b/deps/v8/src/debug.h
@@ -566,18 +566,21 @@ class EventDetailsImpl : public v8::Debug::EventDetails {
EventDetailsImpl(DebugEvent event,
Handle<JSObject> exec_state,
Handle<JSObject> event_data,
- Handle<Object> callback_data);
+ Handle<Object> callback_data,
+ v8::Debug::ClientData* client_data);
virtual DebugEvent GetEvent() const;
virtual v8::Handle<v8::Object> GetExecutionState() const;
virtual v8::Handle<v8::Object> GetEventData() const;
virtual v8::Handle<v8::Context> GetEventContext() const;
virtual v8::Handle<v8::Value> GetCallbackData() const;
+ virtual v8::Debug::ClientData* GetClientData() const;
private:
DebugEvent event_; // Debug event causing the break.
- Handle<JSObject> exec_state_; // Current execution state.
- Handle<JSObject> event_data_; // Data associated with the event.
- Handle<Object> callback_data_; // User data passed with the callback when
- // it was registered.
+ Handle<JSObject> exec_state_; // Current execution state.
+ Handle<JSObject> event_data_; // Data associated with the event.
+ Handle<Object> callback_data_; // User data passed with the callback
+ // when it was registered.
+ v8::Debug::ClientData* client_data_; // Data passed to DebugBreakForCommand.
};
@@ -706,6 +709,9 @@ class Debugger {
// Check whether there are commands in the command queue.
static bool HasCommands();
+ // Enqueue a debugger command to the command queue for event listeners.
+ static void EnqueueDebugCommand(v8::Debug::ClientData* client_data = NULL);
+
static Handle<Object> Call(Handle<JSFunction> fun,
Handle<Object> data,
bool* pending_exception);
@@ -753,6 +759,17 @@ class Debugger {
static bool IsDebuggerActive();
private:
+ static void CallEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ v8::Debug::ClientData* client_data);
+ static void CallCEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ v8::Debug::ClientData* client_data);
+ static void CallJSEventCallback(v8::DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data);
static void ListenersChanged();
static Mutex* debugger_access_; // Mutex guarding debugger variables.
@@ -775,6 +792,8 @@ class Debugger {
static LockingCommandMessageQueue command_queue_;
static Semaphore* command_received_; // Signaled for each command received.
+ static LockingCommandMessageQueue event_command_queue_;
+
friend class EnterDebugger;
};
diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc
index 18be639f39..d65338385e 100644
--- a/deps/v8/src/factory.cc
+++ b/deps/v8/src/factory.cc
@@ -684,7 +684,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name,
int number_of_literals,
Handle<Code> code,
- Handle<Object> scope_info) {
+ Handle<SerializedScopeInfo> scope_info) {
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
shared->set_code(*code);
shared->set_scope_info(*scope_info);
diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h
index 0576d74a6e..22511121cb 100644
--- a/deps/v8/src/factory.h
+++ b/deps/v8/src/factory.h
@@ -351,7 +351,7 @@ class Factory : public AllStatic {
Handle<String> name,
int number_of_literals,
Handle<Code> code,
- Handle<Object> scope_info);
+ Handle<SerializedScopeInfo> scope_info);
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
static Handle<NumberDictionary> DictionaryAtNumberPut(
diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc
index 8b601b67b7..bdd5100ed8 100644
--- a/deps/v8/src/frames.cc
+++ b/deps/v8/src/frames.cc
@@ -532,11 +532,11 @@ void JavaScriptFrame::Print(StringStream* accumulator,
if (IsConstructor()) accumulator->Add("new ");
accumulator->PrintFunction(function, receiver, &code);
- Handle<Object> scope_info(ScopeInfo<>::EmptyHeapObject());
+ Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty());
if (function->IsJSFunction()) {
Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
- scope_info = Handle<Object>(shared->scope_info());
+ scope_info = Handle<SerializedScopeInfo>(shared->scope_info());
Object* script_obj = shared->script();
if (script_obj->IsScript()) {
Handle<Script> script(Script::cast(script_obj));
diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h
index 7bcc964425..6f985eb0d5 100644
--- a/deps/v8/src/globals.h
+++ b/deps/v8/src/globals.h
@@ -326,6 +326,7 @@ class RegExpCompiler;
class RegExpVisitor;
class Scope;
template<class Allocator = FreeStoreAllocationPolicy> class ScopeInfo;
+class SerializedScopeInfo;
class Script;
class Slot;
class Smi;
diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc
index ab0d13fc84..511d390a81 100644
--- a/deps/v8/src/heap.cc
+++ b/deps/v8/src/heap.cc
@@ -2055,7 +2055,7 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
share->set_name(name);
Code* illegal = Builtins::builtin(Builtins::Illegal);
share->set_code(illegal);
- share->set_scope_info(ScopeInfo<>::EmptyHeapObject());
+ share->set_scope_info(SerializedScopeInfo::Empty());
Code* construct_stub = Builtins::builtin(Builtins::JSConstructStubGeneric);
share->set_construct_stub(construct_stub);
share->set_expected_nof_properties(0);
@@ -2480,16 +2480,9 @@ static void FlushCodeForFunction(SharedFunctionInfo* function_info) {
ThreadManager::IterateArchivedThreads(&threadvisitor);
if (threadvisitor.FoundCode()) return;
- // Check that there are heap allocated locals in the scopeinfo. If
- // there is, we are potentially using eval and need the scopeinfo
- // for variable resolution.
- if (ScopeInfo<>::HasHeapAllocatedLocals(function_info->scope_info()))
- return;
-
+ // Compute the lazy compilable version of the code.
HandleScope scope;
- // Compute the lazy compilable version of the code, clear the scope info.
function_info->set_code(*ComputeLazyCompile(function_info->length()));
- function_info->set_scope_info(ScopeInfo<>::EmptyHeapObject());
}
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index 6080a8291c..be5442e7a6 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -11635,6 +11635,8 @@ static int NegativeComparisonResult(Condition cc) {
void CompareStub::Generate(MacroAssembler* masm) {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
Label check_unequal_objects, done;
// NOTICE! This code is only reached after a smi-fast-case check, so
@@ -12528,8 +12530,10 @@ int CompareStub::MinorKey() {
// Encode the three parameters in a unique 16 bit value. To avoid duplicate
// stubs the never NaN NaN condition is only taken into account if the
// condition is equals.
- ASSERT(static_cast<unsigned>(cc_) < (1 << 13));
+ ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
return ConditionField::encode(static_cast<unsigned>(cc_))
+ | RegisterField::encode(false) // lhs_ and rhs_ are not used
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_);
@@ -12539,6 +12543,8 @@ int CompareStub::MinorKey() {
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
const char* CompareStub::GetName() {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
if (name_ != NULL) return name_;
const int kMaxNameLength = 100;
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index ae33948f3a..e81fbc7b75 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -184,6 +184,12 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
// Stop if found the property.
__ cmp(entity_name, Handle<String>(name));
__ j(equal, miss_label, not_taken);
+
+ // Check if the entry name is not a symbol.
+ __ mov(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
+ __ test_b(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ kIsSymbolMask);
+ __ j(zero, miss_label, not_taken);
} else {
// Give up probing if still not found the undefined value.
__ j(not_equal, miss_label, not_taken);
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index 7b874d527c..101096d6c9 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -2511,7 +2511,6 @@ ACCESSORS(BreakPointInfo, break_point_objects, Object, kBreakPointObjectsIndex)
#endif
ACCESSORS(SharedFunctionInfo, name, Object, kNameOffset)
-ACCESSORS(SharedFunctionInfo, scope_info, Object, kScopeInfoOffset)
ACCESSORS(SharedFunctionInfo, construct_stub, Code, kConstructStubOffset)
ACCESSORS(SharedFunctionInfo, instance_class_name, Object,
kInstanceClassNameOffset)
@@ -2648,6 +2647,19 @@ void SharedFunctionInfo::set_code(Code* value, WriteBarrierMode mode) {
}
+SerializedScopeInfo* SharedFunctionInfo::scope_info() {
+ return reinterpret_cast<SerializedScopeInfo*>(
+ READ_FIELD(this, kScopeInfoOffset));
+}
+
+
+void SharedFunctionInfo::set_scope_info(SerializedScopeInfo* value,
+ WriteBarrierMode mode) {
+ WRITE_FIELD(this, kScopeInfoOffset, reinterpret_cast<Object*>(value));
+ CONDITIONAL_WRITE_BARRIER(this, kScopeInfoOffset, mode);
+}
+
+
bool SharedFunctionInfo::is_compiled() {
// TODO(1242782): Create a code kind for uncompiled code.
return code()->kind() != Code::STUB;
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index c2110eabac..b90aced5f7 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -3273,7 +3273,7 @@ class SharedFunctionInfo: public HeapObject {
DECL_ACCESSORS(code, Code)
// [scope_info]: Scope info.
- DECL_ACCESSORS(scope_info, Object)
+ DECL_ACCESSORS(scope_info, SerializedScopeInfo)
// [construct stub]: Code stub for constructing instances of this function.
DECL_ACCESSORS(construct_stub, Code)
diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc
index e215890639..dd5f9bd0d0 100644
--- a/deps/v8/src/parser.cc
+++ b/deps/v8/src/parser.cc
@@ -36,6 +36,7 @@
#include "parser.h"
#include "platform.h"
#include "runtime.h"
+#include "scopeinfo.h"
#include "scopes.h"
#include "string-stream.h"
@@ -1968,8 +1969,9 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
const int literals = fun->NumberOfLiterals();
Handle<Code> code = Handle<Code>(fun->shared()->code());
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
- Handle<SharedFunctionInfo> shared = Factory::NewSharedFunctionInfo(
- name, literals, code, Handle<Object>(fun->shared()->scope_info()));
+ Handle<SharedFunctionInfo> shared =
+ Factory::NewSharedFunctionInfo(name, literals, code,
+ Handle<SerializedScopeInfo>(fun->shared()->scope_info()));
shared->set_construct_stub(*construct_stub);
// Copy the function data to the shared function info.
diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc
index b64ee2ec35..538a9ce931 100644
--- a/deps/v8/src/profile-generator.cc
+++ b/deps/v8/src/profile-generator.cc
@@ -1555,12 +1555,13 @@ void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
JSFunction* func = JSFunction::cast(js_obj);
Context* context = func->context();
ZoneScope zscope(DELETE_ON_EXIT);
- Object* scope_info = context->closure()->shared()->scope_info();
- ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(scope_info);
+ SerializedScopeInfo* serialized_scope_info =
+ context->closure()->shared()->scope_info();
+ ScopeInfo<ZoneListAllocationPolicy> zone_scope_info(serialized_scope_info);
int locals_number = zone_scope_info.NumberOfLocals();
for (int i = 0; i < locals_number; ++i) {
String* local_name = *zone_scope_info.LocalName(i);
- int idx = ScopeInfo<>::ContextSlotIndex(scope_info, local_name, NULL);
+ int idx = serialized_scope_info->ContextSlotIndex(local_name, NULL);
if (idx >= 0 && idx < context->length()) {
snapshot_->SetClosureReference(entry, local_name, context->get(idx));
}
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 535d9a973b..fa881eb203 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -6869,8 +6869,7 @@ static Object* Runtime_NewContext(Arguments args) {
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSFunction, function, args[0]);
- int length =
- ScopeInfo<>::NumberOfContextSlots(function->shared()->scope_info());
+ int length = function->shared()->scope_info()->NumberOfContextSlots();
Object* result = Heap::AllocateFunctionContext(length, function);
if (result->IsFailure()) return result;
@@ -8492,7 +8491,7 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
// Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
- Handle<Object> scope_info(function->shared()->scope_info());
+ Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
ScopeInfo<> info(*scope_info);
// Get the context.
@@ -8521,9 +8520,7 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
}
ASSERT(context->is_function_context());
locals->set(i * 2 + 1,
- context->get(ScopeInfo<>::ContextSlotIndex(*scope_info,
- *name,
- NULL)));
+ context->get(scope_info->ContextSlotIndex(*name, NULL)));
}
}
@@ -8663,18 +8660,17 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
// Copy all the context locals into an object used to materialize a scope.
-static void CopyContextLocalsToScopeObject(Handle<SharedFunctionInfo> shared,
- ScopeInfo<>& scope_info,
- Handle<Context> context,
- Handle<JSObject> scope_object) {
+static void CopyContextLocalsToScopeObject(
+ Handle<SerializedScopeInfo> serialized_scope_info,
+ ScopeInfo<>& scope_info,
+ Handle<Context> context,
+ Handle<JSObject> scope_object) {
// Fill all context locals to the context extension.
for (int i = Context::MIN_CONTEXT_SLOTS;
i < scope_info.number_of_context_slots();
i++) {
- int context_index =
- ScopeInfo<>::ContextSlotIndex(shared->scope_info(),
- *scope_info.context_slot_name(i),
- NULL);
+ int context_index = serialized_scope_info->ContextSlotIndex(
+ *scope_info.context_slot_name(i), NULL);
// Don't include the arguments shadow (.arguments) context variable.
if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) {
@@ -8691,7 +8687,8 @@ static void CopyContextLocalsToScopeObject(Handle<SharedFunctionInfo> shared,
static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<SharedFunctionInfo> shared(function->shared());
- ScopeInfo<> scope_info(shared->scope_info());
+ Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
+ ScopeInfo<> scope_info(*serialized_scope_info);
// Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function.
@@ -8714,7 +8711,7 @@ static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) {
// Third fill all context locals.
Handle<Context> frame_context(Context::cast(frame->context()));
Handle<Context> function_context(frame_context->fcontext());
- CopyContextLocalsToScopeObject(shared, scope_info,
+ CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
function_context, local_scope);
// Finally copy any properties from the function context extension. This will
@@ -8742,7 +8739,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
ASSERT(context->is_function_context());
Handle<SharedFunctionInfo> shared(context->closure()->shared());
- ScopeInfo<> scope_info(shared->scope_info());
+ Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
+ ScopeInfo<> scope_info(*serialized_scope_info);
// Allocate and initialize a JSObject with all the content of theis function
// closure.
@@ -8750,9 +8748,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
// Check whether the arguments shadow object exists.
int arguments_shadow_index =
- ScopeInfo<>::ContextSlotIndex(shared->scope_info(),
- Heap::arguments_shadow_symbol(),
- NULL);
+ shared->scope_info()->ContextSlotIndex(Heap::arguments_shadow_symbol(),
+ NULL);
if (arguments_shadow_index >= 0) {
// In this case all the arguments are available in the arguments shadow
// object.
@@ -8766,7 +8763,8 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) {
}
// Fill all context locals to the context extension.
- CopyContextLocalsToScopeObject(shared, scope_info, context, closure_scope);
+ CopyContextLocalsToScopeObject(serialized_scope_info, scope_info,
+ context, closure_scope);
// Finally copy any properties from the function context extension. This will
// be variables introduced by eval.
@@ -8815,8 +8813,8 @@ class ScopeIterator {
// created for evaluating top level code and it is not a real local scope.
// Checking for the existence of .result seems fragile, but the scope info
// saved with the code object does not otherwise have that information.
- int index = ScopeInfo<>::StackSlotIndex(function_->shared()->scope_info(),
- Heap::result_symbol());
+ int index = function_->shared()->scope_info()->
+ StackSlotIndex(Heap::result_symbol());
at_local_ = index < 0;
} else if (context_->is_function_context()) {
at_local_ = true;
@@ -9454,7 +9452,7 @@ static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
// Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
Handle<JSFunction> function,
- Handle<Object> scope_info,
+ Handle<SerializedScopeInfo> scope_info,
const ScopeInfo<>* sinfo,
Handle<Context> function_context) {
// Try to find the value of 'arguments' to pass as parameter. If it is not
@@ -9462,15 +9460,14 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
// does not support eval) then create an 'arguments' object.
int index;
if (sinfo->number_of_stack_slots() > 0) {
- index = ScopeInfo<>::StackSlotIndex(*scope_info, Heap::arguments_symbol());
+ index = scope_info->StackSlotIndex(Heap::arguments_symbol());
if (index != -1) {
return Handle<Object>(frame->GetExpression(index));
}
}
if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
- index = ScopeInfo<>::ContextSlotIndex(*scope_info, Heap::arguments_symbol(),
- NULL);
+ index = scope_info->ContextSlotIndex(Heap::arguments_symbol(), NULL);
if (index != -1) {
return Handle<Object>(function_context->get(index));
}
@@ -9521,7 +9518,7 @@ static Object* Runtime_DebugEvaluate(Arguments args) {
JavaScriptFrameIterator it(id);
JavaScriptFrame* frame = it.frame();
Handle<JSFunction> function(JSFunction::cast(frame->function()));
- Handle<Object> scope_info(function->shared()->scope_info());
+ Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
ScopeInfo<> sinfo(*scope_info);
// Traverse the saved contexts chain to find the active context for the
diff --git a/deps/v8/src/scopeinfo.cc b/deps/v8/src/scopeinfo.cc
index 16c88b5171..7e7f152597 100644
--- a/deps/v8/src/scopeinfo.cc
+++ b/deps/v8/src/scopeinfo.cc
@@ -204,12 +204,6 @@ static inline Object** ReadSymbol(Object** p, Handle<String>* s) {
}
-static inline Object** ReadSentinel(Object** p) {
- ASSERT(*p == NULL);
- return p + 1;
-}
-
-
template <class Allocator>
static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
ASSERT(list->is_empty());
@@ -220,7 +214,7 @@ static Object** ReadList(Object** p, List<Handle<String>, Allocator >* list) {
p = ReadSymbol(p, &s);
list->Add(s);
}
- return ReadSentinel(p);
+ return p;
}
@@ -239,42 +233,19 @@ static Object** ReadList(Object** p,
list->Add(s);
modes->Add(static_cast<Variable::Mode>(m));
}
- return ReadSentinel(p);
-}
-
-
-template<class Allocator>
-Handle<Object> ScopeInfo<Allocator>::CreateHeapObject(Scope* scope) {
- ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
- return sinfo.Serialize();
-}
-
-
-template<class Allocator>
-Object* ScopeInfo<Allocator>::EmptyHeapObject() {
- return Heap::empty_fixed_array();
-}
-
-
-inline bool IsNotEmpty(Object* data) {
- return FixedArray::cast(data)->length() != 0;
-}
-
-
-inline Object** GetDataStart(Object* data) {
- return FixedArray::cast(data)->data_start();
+ return p;
}
template<class Allocator>
-ScopeInfo<Allocator>::ScopeInfo(Object* data)
+ScopeInfo<Allocator>::ScopeInfo(SerializedScopeInfo* data)
: function_name_(Factory::empty_symbol()),
parameters_(4),
stack_slots_(8),
context_slots_(8),
context_modes_(8) {
- if (IsNotEmpty(data)) {
- Object** p0 = GetDataStart(data);
+ if (data->length() > 0) {
+ Object** p0 = data->data_start();
Object** p = p0;
p = ReadSymbol(p, &function_name_);
p = ReadBool(p, &calls_eval_);
@@ -304,12 +275,6 @@ static inline Object** WriteSymbol(Object** p, Handle<String> s) {
}
-static inline Object** WriteSentinel(Object** p) {
- *p++ = NULL;
- return p;
-}
-
-
template <class Allocator>
static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
const int n = list->length();
@@ -317,7 +282,7 @@ static Object** WriteList(Object** p, List<Handle<String>, Allocator >* list) {
for (int i = 0; i < n; i++) {
p = WriteSymbol(p, list->at(i));
}
- return WriteSentinel(p);
+ return p;
}
@@ -331,23 +296,24 @@ static Object** WriteList(Object** p,
p = WriteSymbol(p, list->at(i));
p = WriteInt(p, modes->at(i));
}
- return WriteSentinel(p);
+ return p;
}
template<class Allocator>
-Handle<Object> ScopeInfo<Allocator>::Serialize() {
- // function name, calls eval, length & sentinel for 3 tables:
- const int extra_slots = 1 + 1 + 2 * 3;
+Handle<SerializedScopeInfo> ScopeInfo<Allocator>::Serialize() {
+ // function name, calls eval, length for 3 tables:
+ const int extra_slots = 1 + 1 + 3;
int length = extra_slots +
context_slots_.length() * 2 +
parameters_.length() +
stack_slots_.length();
- Handle<Object> data(Factory::NewFixedArray(length, TENURED));
+ Handle<SerializedScopeInfo> data(
+ SerializedScopeInfo::cast(*Factory::NewFixedArray(length, TENURED)));
AssertNoAllocation nogc;
- Object** p0 = GetDataStart(*data);
+ Object** p0 = data->data_start();
Object** p = p0;
p = WriteSymbol(p, function_name_);
p = WriteBool(p, calls_eval_);
@@ -360,36 +326,69 @@ Handle<Object> ScopeInfo<Allocator>::Serialize() {
}
-static Object** ContextEntriesAddr(Object* data) {
- ASSERT(IsNotEmpty(data));
- // +2 for function name and calls eval:
- return GetDataStart(data) + 2;
+template<class Allocator>
+Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
+ // A local variable can be allocated either on the stack or in the context.
+ // For variables allocated in the context they are always preceded by
+ // Context::MIN_CONTEXT_SLOTS of fixed allocated slots in the context.
+ if (i < number_of_stack_slots()) {
+ return stack_slot_name(i);
+ } else {
+ return context_slot_name(i - number_of_stack_slots() +
+ Context::MIN_CONTEXT_SLOTS);
+ }
}
-static Object** ParameterEntriesAddr(Object* data) {
- ASSERT(IsNotEmpty(data));
- Object** p = ContextEntriesAddr(data);
- int n; // number of context slots;
- p = ReadInt(p, &n);
- return p + n*2 + 1; // *2 for pairs, +1 for sentinel
+template<class Allocator>
+int ScopeInfo<Allocator>::NumberOfLocals() const {
+ int number_of_locals = number_of_stack_slots();
+ if (number_of_context_slots() > 0) {
+ ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
+ number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
+ }
+ return number_of_locals;
}
-static Object** StackSlotEntriesAddr(Object* data) {
- ASSERT(IsNotEmpty(data));
- Object** p = ParameterEntriesAddr(data);
- int n; // number of parameter slots;
- p = ReadInt(p, &n);
- return p + n + 1; // +1 for sentinel
+Handle<SerializedScopeInfo> SerializedScopeInfo::Create(Scope* scope) {
+ ScopeInfo<ZoneListAllocationPolicy> sinfo(scope);
+ return sinfo.Serialize();
}
-template<class Allocator>
-bool ScopeInfo<Allocator>::CallsEval(Object* data) {
- if (IsNotEmpty(data)) {
- // +1 for function name:
- Object** p = GetDataStart(data) + 1;
+SerializedScopeInfo* SerializedScopeInfo::Empty() {
+ return reinterpret_cast<SerializedScopeInfo*>(Heap::empty_fixed_array());
+}
+
+
+Object** SerializedScopeInfo::ContextEntriesAddr() {
+ ASSERT(length() > 0);
+ return data_start() + 2; // +2 for function name and calls eval.
+}
+
+
+Object** SerializedScopeInfo::ParameterEntriesAddr() {
+ ASSERT(length() > 0);
+ Object** p = ContextEntriesAddr();
+ int number_of_context_slots;
+ p = ReadInt(p, &number_of_context_slots);
+ return p + number_of_context_slots*2; // *2 for pairs
+}
+
+
+Object** SerializedScopeInfo::StackSlotEntriesAddr() {
+ ASSERT(length() > 0);
+ Object** p = ParameterEntriesAddr();
+ int number_of_parameter_slots;
+ p = ReadInt(p, &number_of_parameter_slots);
+ return p + number_of_parameter_slots;
+}
+
+
+bool SerializedScopeInfo::CallsEval() {
+ if (length() > 0) {
+ Object** p = data_start() + 1; // +1 for function name.
bool calls_eval;
p = ReadBool(p, &calls_eval);
return calls_eval;
@@ -398,53 +397,49 @@ bool ScopeInfo<Allocator>::CallsEval(Object* data) {
}
-template<class Allocator>
-int ScopeInfo<Allocator>::NumberOfStackSlots(Object* data) {
- if (IsNotEmpty(data)) {
- Object** p = StackSlotEntriesAddr(data);
- int n; // number of stack slots;
- ReadInt(p, &n);
- return n;
+int SerializedScopeInfo::NumberOfStackSlots() {
+ if (length() > 0) {
+ Object** p = StackSlotEntriesAddr();
+ int number_of_stack_slots;
+ ReadInt(p, &number_of_stack_slots);
+ return number_of_stack_slots;
}
return 0;
}
-template<class Allocator>
-int ScopeInfo<Allocator>::NumberOfContextSlots(Object* data) {
- if (IsNotEmpty(data)) {
- Object** p = ContextEntriesAddr(data);
- int n; // number of context slots;
- ReadInt(p, &n);
- return n + Context::MIN_CONTEXT_SLOTS;
+int SerializedScopeInfo::NumberOfContextSlots() {
+ if (length() > 0) {
+ Object** p = ContextEntriesAddr();
+ int number_of_context_slots;
+ ReadInt(p, &number_of_context_slots);
+ return number_of_context_slots + Context::MIN_CONTEXT_SLOTS;
}
return 0;
}
-template<class Allocator>
-bool ScopeInfo<Allocator>::HasHeapAllocatedLocals(Object* data) {
- if (IsNotEmpty(data)) {
- Object** p = ContextEntriesAddr(data);
- int n; // number of context slots;
- ReadInt(p, &n);
- return n > 0;
+bool SerializedScopeInfo::HasHeapAllocatedLocals() {
+ if (length() > 0) {
+ Object** p = ContextEntriesAddr();
+ int number_of_context_slots;
+ ReadInt(p, &number_of_context_slots);
+ return number_of_context_slots > 0;
}
return false;
}
-template<class Allocator>
-int ScopeInfo<Allocator>::StackSlotIndex(Object* data, String* name) {
+int SerializedScopeInfo::StackSlotIndex(String* name) {
ASSERT(name->IsSymbol());
- if (IsNotEmpty(data)) {
- // Loop below depends on the NULL sentinel after the stack slot names.
- ASSERT(NumberOfStackSlots(data) > 0 ||
- *(StackSlotEntriesAddr(data) + 1) == NULL);
- // slots start after length entry
- Object** p0 = StackSlotEntriesAddr(data) + 1;
+ if (length() > 0) {
+ // Slots start after length entry.
+ Object** p0 = StackSlotEntriesAddr();
+ int number_of_stack_slots;
+ p0 = ReadInt(p0, &number_of_stack_slots);
Object** p = p0;
- while (*p != NULL) {
+ Object** end = p0 + number_of_stack_slots;
+ while (p != end) {
if (*p == name) return static_cast<int>(p - p0);
p++;
}
@@ -452,24 +447,18 @@ int ScopeInfo<Allocator>::StackSlotIndex(Object* data, String* name) {
return -1;
}
-
-template<class Allocator>
-int ScopeInfo<Allocator>::ContextSlotIndex(Object* data,
- String* name,
- Variable::Mode* mode) {
+int SerializedScopeInfo::ContextSlotIndex(String* name, Variable::Mode* mode) {
ASSERT(name->IsSymbol());
- int result = ContextSlotCache::Lookup(data, name, mode);
+ int result = ContextSlotCache::Lookup(this, name, mode);
if (result != ContextSlotCache::kNotFound) return result;
- if (IsNotEmpty(data)) {
- // Loop below depends on the NULL sentinel after the context slot names.
- ASSERT(NumberOfContextSlots(data) >= Context::MIN_CONTEXT_SLOTS ||
- *(ContextEntriesAddr(data) + 1) == NULL);
-
- // slots start after length entry
- Object** p0 = ContextEntriesAddr(data) + 1;
+ if (length() > 0) {
+ // Slots start after length entry.
+ Object** p0 = ContextEntriesAddr();
+ int number_of_context_slots;
+ p0 = ReadInt(p0, &number_of_context_slots);
Object** p = p0;
- // contexts may have no variable slots (in the presence of eval()).
- while (*p != NULL) {
+ Object** end = p0 + number_of_context_slots * 2;
+ while (p != end) {
if (*p == name) {
ASSERT(((p - p0) & 1) == 0);
int v;
@@ -477,21 +466,20 @@ int ScopeInfo<Allocator>::ContextSlotIndex(Object* data,
Variable::Mode mode_value = static_cast<Variable::Mode>(v);
if (mode != NULL) *mode = mode_value;
result = static_cast<int>((p - p0) >> 1) + Context::MIN_CONTEXT_SLOTS;
- ContextSlotCache::Update(data, name, mode_value, result);
+ ContextSlotCache::Update(this, name, mode_value, result);
return result;
}
p += 2;
}
}
- ContextSlotCache::Update(data, name, Variable::INTERNAL, -1);
+ ContextSlotCache::Update(this, name, Variable::INTERNAL, -1);
return -1;
}
-template<class Allocator>
-int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
+int SerializedScopeInfo::ParameterIndex(String* name) {
ASSERT(name->IsSymbol());
- if (IsNotEmpty(data)) {
+ if (length() > 0) {
// We must read parameters from the end since for
// multiply declared parameters the value of the
// last declaration of that parameter is used
@@ -502,10 +490,10 @@ int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
// once, with corresponding index. This requires a new
// implementation of the ScopeInfo code. See also other
// comments in this file regarding this.
- Object** p = ParameterEntriesAddr(data);
- int n; // number of parameters
- Object** p0 = ReadInt(p, &n);
- p = p0 + n;
+ Object** p = ParameterEntriesAddr();
+ int number_of_parameter_slots;
+ Object** p0 = ReadInt(p, &number_of_parameter_slots);
+ p = p0 + number_of_parameter_slots;
while (p > p0) {
p--;
if (*p == name) return static_cast<int>(p - p0);
@@ -515,50 +503,23 @@ int ScopeInfo<Allocator>::ParameterIndex(Object* data, String* name) {
}
-template<class Allocator>
-int ScopeInfo<Allocator>::FunctionContextSlotIndex(Object* data, String* name) {
+int SerializedScopeInfo::FunctionContextSlotIndex(String* name) {
ASSERT(name->IsSymbol());
- if (IsNotEmpty(data)) {
- Object** p = GetDataStart(data);
+ if (length() > 0) {
+ Object** p = data_start();
if (*p == name) {
- p = ContextEntriesAddr(data);
- int n; // number of context slots
- ReadInt(p, &n);
- ASSERT(n != 0);
+ p = ContextEntriesAddr();
+ int number_of_context_slots;
+ ReadInt(p, &number_of_context_slots);
+ ASSERT(number_of_context_slots != 0);
// The function context slot is the last entry.
- return n + Context::MIN_CONTEXT_SLOTS - 1;
+ return number_of_context_slots + Context::MIN_CONTEXT_SLOTS - 1;
}
}
return -1;
}
-template<class Allocator>
-Handle<String> ScopeInfo<Allocator>::LocalName(int i) const {
- // A local variable can be allocated either on the stack or in the context.
- // For variables allocated in the context they are always preceded by the
- // number Context::MIN_CONTEXT_SLOTS number of fixed allocated slots in the
- // context.
- if (i < number_of_stack_slots()) {
- return stack_slot_name(i);
- } else {
- return context_slot_name(i - number_of_stack_slots() +
- Context::MIN_CONTEXT_SLOTS);
- }
-}
-
-
-template<class Allocator>
-int ScopeInfo<Allocator>::NumberOfLocals() const {
- int number_of_locals = number_of_stack_slots();
- if (number_of_context_slots() > 0) {
- ASSERT(number_of_context_slots() >= Context::MIN_CONTEXT_SLOTS);
- number_of_locals += number_of_context_slots() - Context::MIN_CONTEXT_SLOTS;
- }
- return number_of_locals;
-}
-
-
int ContextSlotCache::Hash(Object* data, String* name) {
// Uses only lower 32 bits if pointers are larger.
uintptr_t addr_hash =
diff --git a/deps/v8/src/scopeinfo.h b/deps/v8/src/scopeinfo.h
index 34bbdec47b..0fdab56dbf 100644
--- a/deps/v8/src/scopeinfo.h
+++ b/deps/v8/src/scopeinfo.h
@@ -54,16 +54,11 @@ class ScopeInfo BASE_EMBEDDED {
// Create a ScopeInfo instance from a scope.
explicit ScopeInfo(Scope* scope);
- // Create a ScopeInfo instance from an Object holding the serialized data.
- explicit ScopeInfo(Object* data);
+ // Create a ScopeInfo instance from SerializedScopeInfo.
+ explicit ScopeInfo(SerializedScopeInfo* data);
- // Creates a heap object holding the serialized scope info.
- Handle<Object> Serialize();
-
- static Handle<Object> CreateHeapObject(Scope* scope);
-
- // Serializes empty scope info.
- static Object* EmptyHeapObject();
+ // Creates a SerializedScopeInfo holding the serialized scope info.
+ Handle<SerializedScopeInfo> Serialize();
// --------------------------------------------------------------------------
// Lookup
@@ -88,64 +83,80 @@ class ScopeInfo BASE_EMBEDDED {
int NumberOfLocals() const;
// --------------------------------------------------------------------------
- // The following functions provide quick access to scope info details
- // for runtime routines w/o the need to explicitly create a ScopeInfo
- // object.
- //
- // ScopeInfo is the only class which should have to know about the
- // encoding of it's information in a FixedArray object, which is why these
- // functions are in this class.
+ // Debugging support
+
+#ifdef DEBUG
+ void Print();
+#endif
+
+ private:
+ Handle<String> function_name_;
+ bool calls_eval_;
+ List<Handle<String>, Allocator > parameters_;
+ List<Handle<String>, Allocator > stack_slots_;
+ List<Handle<String>, Allocator > context_slots_;
+ List<Variable::Mode, Allocator > context_modes_;
+};
+
+
+// This object provides quick access to scope info details for runtime
+// routines w/o the need to explicitly create a ScopeInfo object.
+class SerializedScopeInfo : public FixedArray {
+ public :
+
+ static SerializedScopeInfo* cast(Object* object) {
+ ASSERT(object->IsFixedArray());
+ return reinterpret_cast<SerializedScopeInfo*>(object);
+ }
// Does this scope call eval.
- static bool CallsEval(Object* data);
+ bool CallsEval();
// Return the number of stack slots for code.
- static int NumberOfStackSlots(Object* data);
+ int NumberOfStackSlots();
// Return the number of context slots for code.
- static int NumberOfContextSlots(Object* data);
+ int NumberOfContextSlots();
// Return if this has context slots besides MIN_CONTEXT_SLOTS;
- static bool HasHeapAllocatedLocals(Object* data);
+ bool HasHeapAllocatedLocals();
// Lookup support for serialized scope info. Returns the
// the stack slot index for a given slot name if the slot is
// present; otherwise returns a value < 0. The name must be a symbol
// (canonicalized).
- static int StackSlotIndex(Object* data, String* name);
+ int StackSlotIndex(String* name);
// Lookup support for serialized scope info. Returns the
// context slot index for a given slot name if the slot is present; otherwise
// returns a value < 0. The name must be a symbol (canonicalized).
// If the slot is present and mode != NULL, sets *mode to the corresponding
// mode for that variable.
- static int ContextSlotIndex(Object* data, String* name, Variable::Mode* mode);
+ int ContextSlotIndex(String* name, Variable::Mode* mode);
// Lookup support for serialized scope info. Returns the
// parameter index for a given parameter name if the parameter is present;
// otherwise returns a value < 0. The name must be a symbol (canonicalized).
- static int ParameterIndex(Object* data, String* name);
+ int ParameterIndex(String* name);
// Lookup support for serialized scope info. Returns the
// function context slot index if the function name is present (named
// function expressions, only), otherwise returns a value < 0. The name
// must be a symbol (canonicalized).
- static int FunctionContextSlotIndex(Object* data, String* name);
+ int FunctionContextSlotIndex(String* name);
- // --------------------------------------------------------------------------
- // Debugging support
+ static Handle<SerializedScopeInfo> Create(Scope* scope);
-#ifdef DEBUG
- void Print();
-#endif
+ // Serializes empty scope info.
+ static SerializedScopeInfo* Empty();
private:
- Handle<String> function_name_;
- bool calls_eval_;
- List<Handle<String>, Allocator > parameters_;
- List<Handle<String>, Allocator > stack_slots_;
- List<Handle<String>, Allocator > context_slots_;
- List<Variable::Mode, Allocator > context_modes_;
+
+ inline Object** ContextEntriesAddr();
+
+ inline Object** ParameterEntriesAddr();
+
+ inline Object** StackSlotEntriesAddr();
};
diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js
index ffd881fcf6..f77b559638 100644
--- a/deps/v8/src/v8natives.js
+++ b/deps/v8/src/v8natives.js
@@ -745,6 +745,23 @@ function ObjectDefineProperties(obj, properties) {
}
+// ES5 section 15.2.3.8.
+function ObjectSeal(obj) {
+ if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
+ !IS_UNDETECTABLE(obj)) {
+ throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
+ }
+ var names = ObjectGetOwnPropertyNames(obj);
+ for (var key in names) {
+ var name = names[key];
+ var desc = GetOwnProperty(obj, name);
+ if (desc.isConfigurable()) desc.setConfigurable(false);
+ DefineOwnProperty(obj, name, desc, true);
+ }
+ ObjectPreventExtension(obj);
+}
+
+
// ES5 section 15.2.3.9.
function ObjectFreeze(obj) {
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
@@ -774,6 +791,25 @@ function ObjectPreventExtension(obj) {
}
+// ES5 section 15.2.3.11
+function ObjectIsSealed(obj) {
+ if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
+ !IS_UNDETECTABLE(obj)) {
+ throw MakeTypeError("obj_ctor_property_non_object", ["isSealed"]);
+ }
+ var names = ObjectGetOwnPropertyNames(obj);
+ for (var key in names) {
+ var name = names[key];
+ var desc = GetOwnProperty(obj, name);
+ if (desc.isConfigurable()) return false;
+ }
+ if (!ObjectIsExtensible(obj)) {
+ return true;
+ }
+ return false;
+}
+
+
// ES5 section 15.2.3.12
function ObjectIsFrozen(obj) {
if ((!IS_SPEC_OBJECT_OR_NULL(obj) || IS_NULL_OR_UNDEFINED(obj)) &&
@@ -784,8 +820,8 @@ function ObjectIsFrozen(obj) {
for (var key in names) {
var name = names[key];
var desc = GetOwnProperty(obj, name);
- if (IsDataDescriptor(desc) && desc.writable) return false;
- if (desc.configurable) return false;
+ if (IsDataDescriptor(desc) && desc.isWritable()) return false;
+ if (desc.isConfigurable()) return false;
}
if (!ObjectIsExtensible(obj)) {
return true;
@@ -843,7 +879,9 @@ function SetupObject() {
"getOwnPropertyNames", ObjectGetOwnPropertyNames,
"isExtensible", ObjectIsExtensible,
"isFrozen", ObjectIsFrozen,
- "preventExtensions", ObjectPreventExtension
+ "isSealed", ObjectIsSealed,
+ "preventExtensions", ObjectPreventExtension,
+ "seal", ObjectSeal
));
}
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 0a24a6d7c1..65286b6bc3 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -33,8 +33,8 @@
// NOTE these macros are used by the SCons build script so their names
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2
-#define MINOR_VERSION 2
-#define BUILD_NUMBER 24
+#define MINOR_VERSION 3
+#define BUILD_NUMBER 0
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc
index 9917481696..72e7cb3c1d 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -3428,49 +3428,56 @@ void CodeGenerator::GenerateFastSmiLoop(ForStatement* node) {
CodeForStatementPosition(node);
Slot* loop_var_slot = loop_var->slot();
if (loop_var_slot->type() == Slot::LOCAL) {
- frame_->PushLocalAt(loop_var_slot->index());
+ frame_->TakeLocalAt(loop_var_slot->index());
} else {
ASSERT(loop_var_slot->type() == Slot::PARAMETER);
- frame_->PushParameterAt(loop_var_slot->index());
+ frame_->TakeParameterAt(loop_var_slot->index());
}
Result loop_var_result = frame_->Pop();
if (!loop_var_result.is_register()) {
loop_var_result.ToRegister();
}
-
+ Register loop_var_reg = loop_var_result.reg();
+ frame_->Spill(loop_var_reg);
if (increments) {
- __ SmiAddConstant(loop_var_result.reg(),
- loop_var_result.reg(),
+ __ SmiAddConstant(loop_var_reg,
+ loop_var_reg,
Smi::FromInt(1));
} else {
- __ SmiSubConstant(loop_var_result.reg(),
- loop_var_result.reg(),
+ __ SmiSubConstant(loop_var_reg,
+ loop_var_reg,
Smi::FromInt(1));
}
- {
- __ SmiCompare(loop_var_result.reg(), limit_value);
- Condition condition;
- switch (compare_op) {
- case Token::LT:
- condition = less;
- break;
- case Token::LTE:
- condition = less_equal;
- break;
- case Token::GT:
- condition = greater;
- break;
- case Token::GTE:
- condition = greater_equal;
- break;
- default:
- condition = never;
- UNREACHABLE();
- }
- loop.Branch(condition);
+ frame_->Push(&loop_var_result);
+ if (loop_var_slot->type() == Slot::LOCAL) {
+ frame_->StoreToLocalAt(loop_var_slot->index());
+ } else {
+ ASSERT(loop_var_slot->type() == Slot::PARAMETER);
+ frame_->StoreToParameterAt(loop_var_slot->index());
}
- loop_var_result.Unuse();
+ frame_->Drop();
+
+ __ SmiCompare(loop_var_reg, limit_value);
+ Condition condition;
+ switch (compare_op) {
+ case Token::LT:
+ condition = less;
+ break;
+ case Token::LTE:
+ condition = less_equal;
+ break;
+ case Token::GT:
+ condition = greater;
+ break;
+ case Token::GTE:
+ condition = greater_equal;
+ break;
+ default:
+ condition = never;
+ UNREACHABLE();
+ }
+ loop.Branch(condition);
}
if (node->break_target()->is_linked()) {
node->break_target()->Bind();
@@ -10094,6 +10101,8 @@ static int NegativeComparisonResult(Condition cc) {
void CompareStub::Generate(MacroAssembler* masm) {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
Label check_unequal_objects, done;
// The compare stub returns a positive, negative, or zero 64-bit integer
// value in rax, corresponding to result of comparing the two inputs.
@@ -10942,8 +10951,10 @@ int CompareStub::MinorKey() {
// Encode the three parameters in a unique 16 bit value. To avoid duplicate
// stubs the never NaN NaN condition is only taken into account if the
// condition is equals.
- ASSERT(static_cast<unsigned>(cc_) < (1 << 13));
+ ASSERT(static_cast<unsigned>(cc_) < (1 << 12));
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
return ConditionField::encode(static_cast<unsigned>(cc_))
+ | RegisterField::encode(false) // lhs_ and rhs_ are not used
| StrictField::encode(strict_)
| NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
| IncludeNumberCompareField::encode(include_number_compare_);
@@ -10953,6 +10964,8 @@ int CompareStub::MinorKey() {
// Unfortunately you have to run without snapshots to see most of these
// names in the profile since most compare stubs end up in the snapshot.
const char* CompareStub::GetName() {
+ ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
+
if (name_ != NULL) return name_;
const int kMaxNameLength = 100;
name_ = Bootstrapper::AllocateAutoDeletedArray(kMaxNameLength);
diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc
index 53301cc461..2a918f1687 100644
--- a/deps/v8/src/x64/stub-cache-x64.cc
+++ b/deps/v8/src/x64/stub-cache-x64.cc
@@ -164,6 +164,12 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
// Stop if found the property.
__ Cmp(entity_name, Handle<String>(name));
__ j(equal, miss_label);
+
+ // Check if the entry name is not a symbol.
+ __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset));
+ __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset),
+ Immediate(kIsSymbolMask));
+ __ j(zero, miss_label);
} else {
// Give up probing if still not found the undefined value.
__ j(not_equal, miss_label);
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index 8ebf7522a6..6a94bedbb2 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -6650,4 +6650,69 @@ TEST(DebugEventContext) {
CheckDebuggerUnloaded();
}
+
+static void* expected_break_data;
+static bool was_debug_break_called;
+static bool was_debug_event_called;
+static void DebugEventBreakDataChecker(const v8::Debug::EventDetails& details) {
+ if (details.GetEvent() == v8::BreakForCommand) {
+ CHECK_EQ(expected_break_data, details.GetClientData());
+ was_debug_event_called = true;
+ } else if (details.GetEvent() == v8::Break) {
+ was_debug_break_called = true;
+ }
+}
+
+// Check that event details contain context where debug event occured.
+TEST(DebugEventBreakData) {
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ v8::Debug::SetDebugEventListener2(DebugEventBreakDataChecker);
+
+ TestClientData::constructor_call_counter = 0;
+ TestClientData::destructor_call_counter = 0;
+
+ expected_break_data = NULL;
+ was_debug_event_called = false;
+ was_debug_break_called = false;
+ v8::Debug::DebugBreakForCommand();
+ v8::Script::Compile(v8::String::New("(function(x){return x;})(1);"))->Run();
+ CHECK(was_debug_event_called);
+ CHECK(!was_debug_break_called);
+
+ TestClientData* data1 = new TestClientData();
+ expected_break_data = data1;
+ was_debug_event_called = false;
+ was_debug_break_called = false;
+ v8::Debug::DebugBreakForCommand(data1);
+ v8::Script::Compile(v8::String::New("(function(x){return x+1;})(1);"))->Run();
+ CHECK(was_debug_event_called);
+ CHECK(!was_debug_break_called);
+
+ expected_break_data = NULL;
+ was_debug_event_called = false;
+ was_debug_break_called = false;
+ v8::Debug::DebugBreak();
+ v8::Script::Compile(v8::String::New("(function(x){return x+2;})(1);"))->Run();
+ CHECK(!was_debug_event_called);
+ CHECK(was_debug_break_called);
+
+ TestClientData* data2 = new TestClientData();
+ expected_break_data = data2;
+ was_debug_event_called = false;
+ was_debug_break_called = false;
+ v8::Debug::DebugBreak();
+ v8::Debug::DebugBreakForCommand(data2);
+ v8::Script::Compile(v8::String::New("(function(x){return x+3;})(1);"))->Run();
+ CHECK(was_debug_event_called);
+ CHECK(was_debug_break_called);
+
+ CHECK_EQ(2, TestClientData::constructor_call_counter);
+ CHECK_EQ(TestClientData::constructor_call_counter,
+ TestClientData::destructor_call_counter);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
+
#endif // ENABLE_DEBUGGER_SUPPORT
diff --git a/deps/v8/test/es5conform/es5conform.status b/deps/v8/test/es5conform/es5conform.status
index 4fb8f7bf17..5add082c63 100644
--- a/deps/v8/test/es5conform/es5conform.status
+++ b/deps/v8/test/es5conform/es5conform.status
@@ -47,17 +47,6 @@ chapter11/11.4/11.4.1//11.4.1-4.a-7: FAIL
# We do not have a global object called 'global' as required by tests.
chapter15/15.1: FAIL_OK
-# NOT IMPLEMENTED: seal
-chapter15/15.2/15.2.3/15.2.3.8: UNIMPLEMENTED
-# NOT IMPLEMENTED: isSealed
-chapter15/15.2/15.2.3/15.2.3.11: UNIMPLEMENTED
-
-# NOT IMPLEMENTED: seal
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-20: UNIMPLEMENTED
-
-# NOT IMPLEMENTED: isSealed
-chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-23: UNIMPLEMENTED
-
# NOT IMPLEMENTED: bind
chapter15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-38: UNIMPLEMENTED
diff --git a/deps/v8/test/mjsunit/call-stub.js b/deps/v8/test/mjsunit/call-stub.js
index a9132a6bd0..9d11649e7a 100644
--- a/deps/v8/test/mjsunit/call-stub.js
+++ b/deps/v8/test/mjsunit/call-stub.js
@@ -49,3 +49,18 @@ for (var i = 1; i < 100; i++) {
}
assertEquals(i < 50 || i >= 70 ? 1 : 2, h.m());
}
+
+
+var nonsymbol = 'wwwww '.split(' ')[0];
+Hash.prototype.wwwww = Hash.prototype.m;
+
+for (var i = 1; i < 100; i++) {
+ if (i == 50) {
+ h[nonsymbol] = function() {
+ return 2;
+ };
+ } else if (i == 70) {
+ delete h[nonsymbol];
+ }
+ assertEquals(i < 50 || i >= 70 ? 1 : 2, h.wwwww());
+}
diff --git a/deps/v8/test/mjsunit/object-freeze.js b/deps/v8/test/mjsunit/object-freeze.js
index 0ac617762a..5ab45e1f27 100644
--- a/deps/v8/test/mjsunit/object-freeze.js
+++ b/deps/v8/test/mjsunit/object-freeze.js
@@ -172,3 +172,22 @@ Object.defineProperty(obj3, 'y', {configurable: false, writable: false});
Object.preventExtensions(obj3);
assertTrue(Object.isFrozen(obj3));
+
+
+// Make sure that an object that has only non-configurable, but one
+// writable property, is not classified as frozen.
+var obj4 = {};
+Object.defineProperty(obj4, 'x', {configurable: false, writable: true});
+Object.defineProperty(obj4, 'y', {configurable: false, writable: false});
+Object.preventExtensions(obj4);
+
+assertFalse(Object.isFrozen(obj4));
+
+// Make sure that an object that has only non-writable, but one
+// configurable property, is not classified as frozen.
+var obj5 = {};
+Object.defineProperty(obj5, 'x', {configurable: true, writable: false});
+Object.defineProperty(obj5, 'y', {configurable: false, writable: false});
+Object.preventExtensions(obj5);
+
+assertFalse(Object.isFrozen(obj5));
diff --git a/deps/v8/test/mjsunit/object-seal.js b/deps/v8/test/mjsunit/object-seal.js
new file mode 100644
index 0000000000..896411ca3f
--- /dev/null
+++ b/deps/v8/test/mjsunit/object-seal.js
@@ -0,0 +1,195 @@
+// 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.
+
+// Tests the Object.seal and Object.isSealed methods - ES 15.2.3.9 and
+// ES 15.2.3.12
+
+
+// Test that we throw an error if an object is not passed as argument.
+var non_objects = new Array(undefined, null, 1, -1, 0, 42.43);
+for (var key in non_objects) {
+ try {
+ Object.seal(non_objects[key]);
+ assertUnreachable();
+ } catch(e) {
+ assertTrue(/Object.seal called on non-object/.test(e));
+ }
+}
+
+for (var key in non_objects) {
+ try {
+ Object.isSealed(non_objects[key]);
+ assertUnreachable();
+ } catch(e) {
+ assertTrue(/Object.isSealed called on non-object/.test(e));
+ }
+}
+
+// Test normal data properties.
+var obj = { x: 42, z: 'foobar' };
+var desc = Object.getOwnPropertyDescriptor(obj, 'x');
+assertTrue(desc.writable);
+assertTrue(desc.configurable);
+assertEquals(42, desc.value);
+
+desc = Object.getOwnPropertyDescriptor(obj, 'z');
+assertTrue(desc.writable);
+assertTrue(desc.configurable);
+assertEquals('foobar', desc.value);
+
+assertTrue(Object.isExtensible(obj));
+assertFalse(Object.isSealed(obj));
+
+Object.seal(obj);
+
+// Make sure we are no longer extensible.
+assertFalse(Object.isExtensible(obj));
+assertTrue(Object.isSealed(obj));
+
+// We should not be frozen, since we are still able to
+// update values.
+assertFalse(Object.isFrozen(obj));
+
+// We should not allow new properties to be added.
+try {
+ obj.foo = 42;
+ assertUnreachable();
+} catch(e) {
+ assertTrue(/object is not extensible/.test(e));
+}
+
+desc = Object.getOwnPropertyDescriptor(obj, 'x');
+assertTrue(desc.writable);
+assertFalse(desc.configurable);
+assertEquals(42, desc.value);
+
+desc = Object.getOwnPropertyDescriptor(obj, 'z');
+assertTrue(desc.writable);
+assertFalse(desc.configurable);
+assertEquals("foobar", desc.value);
+
+// Since writable is not affected by seal we should still be able to
+// update the values.
+obj.x = "43";
+assertEquals(43, obj.x);
+
+// Test on accessors.
+var obj2 = {};
+function get() { return 43; };
+function set() {};
+Object.defineProperty(obj2, 'x', { get: get, set: set, configurable: true });
+
+desc = Object.getOwnPropertyDescriptor(obj2, 'x');
+assertTrue(desc.configurable);
+assertEquals(undefined, desc.value);
+assertEquals(set, desc.set);
+assertEquals(get, desc.get);
+
+assertTrue(Object.isExtensible(obj2));
+assertFalse(Object.isSealed(obj2));
+Object.seal(obj2);
+
+// Since this is an accessor property the object is now effectively both
+// sealed and frozen (accessors has no writable attribute).
+assertTrue(Object.isFrozen(obj2));
+assertFalse(Object.isExtensible(obj2));
+assertTrue(Object.isSealed(obj2));
+
+desc = Object.getOwnPropertyDescriptor(obj2, 'x');
+assertFalse(desc.configurable);
+assertEquals(undefined, desc.value);
+assertEquals(set, desc.set);
+assertEquals(get, desc.get);
+
+try {
+ obj2.foo = 42;
+ assertUnreachable();
+} catch(e) {
+ assertTrue(/object is not extensible/.test(e));
+}
+
+
+// Test seal on arrays.
+var arr = new Array(42,43);
+
+desc = Object.getOwnPropertyDescriptor(arr, '0');
+assertTrue(desc.configurable);
+assertTrue(desc.writable);
+assertEquals(42, desc.value);
+
+desc = Object.getOwnPropertyDescriptor(arr, '1');
+assertTrue(desc.configurable);
+assertTrue(desc.writable);
+assertEquals(43, desc.value);
+
+assertTrue(Object.isExtensible(arr));
+assertFalse(Object.isSealed(arr));
+Object.seal(arr);
+assertTrue(Object.isSealed(arr));
+assertFalse(Object.isExtensible(arr));
+// Since the values in the array is still writable this object
+// is not frozen.
+assertFalse(Object.isFrozen(arr));
+
+desc = Object.getOwnPropertyDescriptor(arr, '0');
+assertFalse(desc.configurable);
+assertTrue(desc.writable);
+assertEquals(42, desc.value);
+
+desc = Object.getOwnPropertyDescriptor(arr, '1');
+assertFalse(desc.configurable);
+assertTrue(desc.writable);
+assertEquals(43, desc.value);
+
+arr[0] = 'foo';
+
+// We should be able to overwrite the existing value.
+assertEquals('foo', arr[0]);
+
+
+// Test that isSealed returns the correct value even if configurable
+// has been set to false on all properties manually and the extensible
+// flag has also been set to false manually.
+var obj3 = { x: 42, y: 'foo' };
+
+assertFalse(Object.isFrozen(obj3));
+
+Object.defineProperty(obj3, 'x', {configurable: false, writable: true});
+Object.defineProperty(obj3, 'y', {configurable: false, writable: false});
+Object.preventExtensions(obj3);
+
+assertTrue(Object.isSealed(obj3));
+
+
+// Make sure that an object that has a configurable property
+// is not classified as sealed.
+var obj4 = {};
+Object.defineProperty(obj4, 'x', {configurable: true, writable: false});
+Object.defineProperty(obj4, 'y', {configurable: false, writable: false});
+Object.preventExtensions(obj4);
+
+assertFalse(Object.isSealed(obj4));
diff --git a/deps/v8/test/mjsunit/regress/regress-r4998.js b/deps/v8/test/mjsunit/regress/regress-r4998.js
new file mode 100644
index 0000000000..9cf33713b5
--- /dev/null
+++ b/deps/v8/test/mjsunit/regress/regress-r4998.js
@@ -0,0 +1,94 @@
+// 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 for a broken fast-smi-loop that does not save the incremented value
+// of the loop index. If this test fails, it loops forever, and times out.
+
+// Flags: --nofull-compiler
+
+// Calling foo() spills the virtual frame.
+function foo() {
+ return;
+}
+
+function bar() {
+ var x1 = 3;
+ var x2 = 3;
+ var x3 = 3;
+ var x4 = 3;
+ var x5 = 3;
+ var x6 = 3;
+ var x7 = 3;
+ var x8 = 3;
+ var x9 = 3;
+ var x10 = 3;
+ var x11 = 3;
+ var x12 = 3;
+ var x13 = 3;
+
+ foo();
+
+ x1 = 257;
+ x2 = 258;
+ x3 = 259;
+ x4 = 260;
+ x5 = 261;
+ x6 = 262;
+ x7 = 263;
+ x8 = 264;
+ x9 = 265;
+ x10 = 266;
+ x11 = 267;
+ x12 = 268;
+ x13 = 269;
+
+ // The loop variable x7 is initialized to 3,
+ // and then MakeMergeable is called on the virtual frame.
+ // MakeMergeable has forced the loop variable x7 to be spilled,
+ // so it is marked as synced
+ // The back edge then merges its virtual frame, which incorrectly
+ // claims that x7 is synced, and does not save the modified
+ // value.
+ for (x7 = 3; x7 < 10; ++x7) {
+ foo();
+ }
+}
+
+bar();
+
+function aliasing() {
+ var x = 3;
+ var j;
+ for (j = 7; j < 11; ++j) {
+ x = j;
+ }
+
+ assertEquals(10, x);
+ assertEquals(11, j);
+}
+
+aliasing();