summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps/v8/ChangeLog7
-rw-r--r--deps/v8/src/api.h9
-rw-r--r--deps/v8/src/arm/codegen-arm.cc18
-rw-r--r--deps/v8/src/arm/fast-codegen-arm.cc225
-rw-r--r--deps/v8/src/arm/frames-arm.cc15
-rw-r--r--deps/v8/src/arm/frames-arm.h2
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.cc19
-rw-r--r--deps/v8/src/arm/macro-assembler-arm.h8
-rw-r--r--deps/v8/src/assembler.cc25
-rw-r--r--deps/v8/src/assembler.h8
-rw-r--r--deps/v8/src/ast.h2
-rw-r--r--deps/v8/src/code-stubs.cc48
-rw-r--r--deps/v8/src/code-stubs.h7
-rw-r--r--deps/v8/src/codegen.cc16
-rw-r--r--deps/v8/src/codegen.h28
-rw-r--r--deps/v8/src/compiler.cc32
-rw-r--r--deps/v8/src/fast-codegen.cc28
-rw-r--r--deps/v8/src/fast-codegen.h5
-rw-r--r--deps/v8/src/frames.cc18
-rw-r--r--deps/v8/src/frames.h25
-rw-r--r--deps/v8/src/globals.h4
-rw-r--r--deps/v8/src/handles.cc15
-rw-r--r--deps/v8/src/handles.h10
-rw-r--r--deps/v8/src/ia32/codegen-ia32.cc91
-rw-r--r--deps/v8/src/ia32/fast-codegen-ia32.cc224
-rw-r--r--deps/v8/src/ia32/frames-ia32.cc13
-rw-r--r--deps/v8/src/ia32/frames-ia32.h2
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.cc96
-rw-r--r--deps/v8/src/ia32/macro-assembler-ia32.h16
-rw-r--r--deps/v8/src/ia32/stub-cache-ia32.cc39
-rw-r--r--deps/v8/src/location.h19
-rw-r--r--deps/v8/src/objects-debug.cc1
-rw-r--r--deps/v8/src/objects-inl.h1
-rw-r--r--deps/v8/src/objects.h4
-rw-r--r--deps/v8/src/runtime.cc64
-rw-r--r--deps/v8/src/runtime.h3
-rw-r--r--deps/v8/src/string.js9
-rw-r--r--deps/v8/src/stub-cache.cc7
-rw-r--r--deps/v8/src/top.h4
-rw-r--r--deps/v8/src/version.cc2
-rw-r--r--deps/v8/src/x64/codegen-x64.cc23
-rw-r--r--deps/v8/src/x64/fast-codegen-x64.cc226
-rw-r--r--deps/v8/src/x64/frames-x64.cc14
-rw-r--r--deps/v8/src/x64/frames-x64.h2
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.cc19
-rw-r--r--deps/v8/src/x64/macro-assembler-x64.h8
-rw-r--r--deps/v8/test/cctest/SConscript1
-rw-r--r--deps/v8/test/cctest/cctest.cc3
-rw-r--r--deps/v8/test/cctest/cctest.h136
-rw-r--r--deps/v8/test/cctest/test-accessors.cc424
-rw-r--r--deps/v8/test/cctest/test-api.cc352
-rw-r--r--deps/v8/test/cctest/test-debug.cc6
-rw-r--r--deps/v8/test/cctest/test-log-stack-tracer.cc5
-rw-r--r--deps/v8/test/mjsunit/fuzz-natives.js4
54 files changed, 1022 insertions, 1370 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog
index e816f5833f..8ee83766a4 100644
--- a/deps/v8/ChangeLog
+++ b/deps/v8/ChangeLog
@@ -1,3 +1,10 @@
+2009-10-29: Version 1.3.18
+
+ Reverted a change which caused crashes in RegExp replace.
+
+ Reverted a change which caused Chromium ui_tests failure.
+
+
2009-10-28: Version 1.3.17
Added API method to get simple heap statistics.
diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h
index a28e1f0774..1221f352cc 100644
--- a/deps/v8/src/api.h
+++ b/deps/v8/src/api.h
@@ -125,15 +125,6 @@ static inline v8::internal::Handle<v8::internal::Object> FromCData(T obj) {
}
-class ApiFunction {
- public:
- explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
- v8::internal::Address address() { return addr_; }
- private:
- v8::internal::Address addr_;
-};
-
-
v8::Arguments::Arguments(v8::Local<v8::Value> data,
v8::Local<v8::Object> holder,
v8::Local<v8::Function> callee,
diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc
index 3292bdcff2..dd88515e7a 100644
--- a/deps/v8/src/arm/codegen-arm.cc
+++ b/deps/v8/src/arm/codegen-arm.cc
@@ -5795,7 +5795,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
Label* throw_termination_exception,
Label* throw_out_of_memory_exception,
- ExitFrame::Mode mode,
+ StackFrame::Type frame_type,
bool do_gc,
bool always_allocate) {
// r0: result parameter for PerformGC, if any
@@ -5855,7 +5855,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
// r0:r1: result
// sp: stack pointer
// fp: frame pointer
- __ LeaveExitFrame(mode);
+ __ LeaveExitFrame(frame_type);
// check if we should retry or throw exception
Label retry;
@@ -5901,12 +5901,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// this by performing a garbage collection and retrying the
// builtin once.
- ExitFrame::Mode mode = is_debug_break
- ? ExitFrame::MODE_DEBUG
- : ExitFrame::MODE_NORMAL;
+ StackFrame::Type frame_type = is_debug_break
+ ? StackFrame::EXIT_DEBUG
+ : StackFrame::EXIT;
// Enter the exit frame that transitions from JavaScript to C++.
- __ EnterExitFrame(mode);
+ __ EnterExitFrame(frame_type);
// r4: number of arguments (C callee-saved)
// r5: pointer to builtin function (C callee-saved)
@@ -5921,7 +5921,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
false,
false);
@@ -5930,7 +5930,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
true,
false);
@@ -5941,7 +5941,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
true,
true);
diff --git a/deps/v8/src/arm/fast-codegen-arm.cc b/deps/v8/src/arm/fast-codegen-arm.cc
index 21ee6d7e02..6540d40165 100644
--- a/deps/v8/src/arm/fast-codegen-arm.cc
+++ b/deps/v8/src/arm/fast-codegen-arm.cc
@@ -119,9 +119,11 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
__ ldr(ip, MemOperand(fp, SlotOffset(source)));
__ push(ip);
break;
@@ -131,9 +133,11 @@ void FastCodeGenerator::Move(Location destination, Slot* source) {
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
__ mov(ip, Operand(expr->handle()));
__ push(ip);
break;
@@ -143,9 +147,10 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) {
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized: // Fall through.
+ case Location::kEffect:
UNREACHABLE();
- case Location::TEMP:
+ case Location::kValue:
__ pop(ip);
__ str(ip, MemOperand(fp, SlotOffset(destination)));
break;
@@ -155,10 +160,12 @@ void FastCodeGenerator::Move(Slot* destination, Location source) {
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
__ pop();
break;
- case Location::TEMP:
+ case Location::kValue:
__ str(source, MemOperand(sp));
break;
}
@@ -239,6 +246,33 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ Comment cmnt(masm_, "[ RegExp Literal");
+ Label done;
+ // Registers will be used as follows:
+ // r4 = JS function, literals array
+ // r3 = literal index
+ // r2 = RegExp pattern
+ // r1 = RegExp flags
+ // r0 = temp + return value (RegExp literal)
+ __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+ __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
+ int literal_offset =
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+ __ ldr(r0, FieldMemOperand(r4, literal_offset));
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
+ __ cmp(r0, ip);
+ __ b(ne, &done);
+ __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
+ __ mov(r2, Operand(expr->pattern()));
+ __ mov(r1, Operand(expr->flags()));
+ __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+ __ bind(&done);
+ Move(expr->location(), r0);
+}
+
+
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
Label boilerplate_exists;
@@ -284,73 +318,62 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
result_saved = true;
}
switch (property->kind()) {
- case ObjectLiteral::Property::MATERIALIZED_LITERAL: // fall through
+ case ObjectLiteral::Property::CONSTANT:
+ UNREACHABLE();
+
+ case ObjectLiteral::Property::MATERIALIZED_LITERAL: // Fall through.
ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
- case ObjectLiteral::Property::COMPUTED: // fall through
+ case ObjectLiteral::Property::COMPUTED:
+ if (key->handle()->IsSymbol()) {
+ Visit(value);
+ Move(r0, value->location());
+ __ mov(r2, Operand(key->handle()));
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
+ __ Call(ic, RelocInfo::CODE_TARGET);
+ // StoreIC leaves the receiver on the stack.
+ break;
+ }
+ // Fall through.
+
case ObjectLiteral::Property::PROTOTYPE:
__ push(r0);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kSetProperty, 3);
__ ldr(r0, MemOperand(sp)); // Restore result into r0
break;
- case ObjectLiteral::Property::SETTER: // fall through
- case ObjectLiteral::Property::GETTER:
+
+ case ObjectLiteral::Property::GETTER: // Fall through.
+ case ObjectLiteral::Property::SETTER:
__ push(r0);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
__ mov(r1, Operand(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
__ push(r1);
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ ldr(r0, MemOperand(sp)); // Restore result into r0
break;
- default: UNREACHABLE();
}
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
if (result_saved) __ pop();
break;
- case Location::TEMP:
+ case Location::kValue:
if (!result_saved) __ push(r0);
break;
}
}
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
- Comment cmnt(masm_, "[ RegExp Literal");
- Label done;
- // Registers will be used as follows:
- // r4 = JS function, literals array
- // r3 = literal index
- // r2 = RegExp pattern
- // r1 = RegExp flags
- // r0 = temp + return value (RegExp literal)
- __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
- __ ldr(r4, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
- int literal_offset =
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
- __ ldr(r0, FieldMemOperand(r4, literal_offset));
- __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
- __ cmp(r0, ip);
- __ b(ne, &done);
- __ mov(r3, Operand(Smi::FromInt(expr->literal_index())));
- __ mov(r2, Operand(expr->pattern()));
- __ mov(r1, Operand(expr->flags()));
- __ stm(db_w, sp, r4.bit() | r3.bit() | r2.bit() | r1.bit());
- __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- __ bind(&done);
- Move(expr->location(), r0);
-}
-
-
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
Label make_clone;
@@ -400,7 +423,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
result_saved = true;
}
Visit(subexpr);
- ASSERT(subexpr->location().is_temporary());
+ ASSERT(subexpr->location().is_value());
// Store the subexpression value in the array's elements.
__ pop(r0); // Subexpression value.
@@ -416,10 +439,12 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
if (result_saved) __ pop();
break;
- case Location::TEMP:
+ case Location::kValue:
if (!result_saved) __ push(r0);
break;
}
@@ -446,7 +471,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
if (rhs->AsLiteral() != NULL) {
__ mov(r0, Operand(rhs->AsLiteral()->handle()));
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
__ pop(r0);
}
@@ -468,15 +493,17 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ str(ip, MemOperand(fp, SlotOffset(var->slot())));
Move(expr->location(), ip);
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
// Load right-hand side into ip.
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
// Case 'var = temp'. Discard right-hand-side temporary.
__ pop(ip);
break;
- case Location::TEMP:
+ case Location::kValue:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ ldr(ip, MemOperand(sp));
@@ -522,10 +549,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
__ pop();
}
switch (expr->location().type()) {
- case Location::TEMP:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kValue:
__ str(r0, MemOperand(sp));
break;
- case Location::NOWHERE:
+ case Location::kEffect:
__ pop();
}
}
@@ -546,7 +575,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
// Record source position for debugger
SetSourcePosition(expr->position());
@@ -567,7 +596,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
// arguments.
// Push function on the stack.
Visit(node->expression());
- ASSERT(node->expression()->location().is_temporary());
+ ASSERT(node->expression()->location().is_value());
// Push global object (receiver).
__ ldr(r0, CodeGenerator::GlobalObject());
@@ -577,8 +606,8 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
- // If location is temporary, it is already on the stack,
+ ASSERT(args->at(i)->location().is_value());
+ // If location is value, it is already on the stack,
// so nothing to do here.
}
@@ -610,7 +639,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
__ CallRuntime(function, arg_count);
@@ -619,11 +648,57 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
- // Compile a short-circuited boolean or operation in a non-test
- // context.
- ASSERT(expr->op() == Token::OR);
+ switch (expr->op()) {
+ case Token::COMMA:
+ ASSERT(expr->left()->location().is_effect());
+ ASSERT_EQ(expr->right()->location().type(), expr->location().type());
+ Visit(expr->left());
+ Visit(expr->right());
+ break;
+
+ case Token::OR:
+ case Token::AND:
+ EmitLogicalOperation(expr);
+ break;
+
+ case Token::ADD:
+ case Token::SUB:
+ case Token::DIV:
+ case Token::MOD:
+ case Token::MUL:
+ case Token::BIT_OR:
+ case Token::BIT_AND:
+ case Token::BIT_XOR:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::SAR: {
+ ASSERT(expr->left()->location().is_value());
+ ASSERT(expr->right()->location().is_value());
+
+ Visit(expr->left());
+ Visit(expr->right());
+ __ pop(r0);
+ __ pop(r1);
+ GenericBinaryOpStub stub(expr->op(),
+ NO_OVERWRITE);
+ __ CallStub(&stub);
+ Move(expr->location(), r0);
+
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
+ // Compile a short-circuited boolean operation in a non-test context.
+
// Compile (e0 || e1) as if it were
// (let (temp = e0) temp ? temp : e1).
+ // Compile (e0 && e1) as if it were
+ // (let (temp = e0) !temp ? temp : e1).
Label done;
Location destination = expr->location();
@@ -636,31 +711,31 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
if (left->AsLiteral() != NULL) {
__ mov(r0, Operand(left->AsLiteral()->handle()));
__ push(r0);
- if (destination.is_temporary()) __ push(r0);
+ if (destination.is_value()) __ push(r0);
} else {
Visit(left);
- ASSERT(left->location().is_temporary());
- if (destination.is_temporary()) {
+ ASSERT(left->location().is_value());
+ if (destination.is_value()) {
__ ldr(r0, MemOperand(sp));
__ push(r0);
}
}
// The left-hand value is in on top of the stack. It is duplicated on the
- // stack iff the destination location is temporary.
+ // stack iff the destination location is value.
__ CallRuntime(Runtime::kToBool, 1);
- __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+ if (expr->op() == Token::OR) {
+ __ LoadRoot(ip, Heap::kTrueValueRootIndex);
+ } else {
+ __ LoadRoot(ip, Heap::kFalseValueRootIndex);
+ }
__ cmp(r0, ip);
__ b(eq, &done);
// Discard the left-hand value if present on the stack.
- if (destination.is_temporary()) __ pop();
+ if (destination.is_value()) __ pop();
// Save or discard the right-hand value as needed.
- if (right->AsLiteral() != NULL) {
- Move(destination, right->AsLiteral());
- } else {
- Visit(right);
- Move(destination, right->location());
- }
+ Visit(right);
+ ASSERT_EQ(destination.type(), right->location().type());
__ bind(&done);
}
diff --git a/deps/v8/src/arm/frames-arm.cc b/deps/v8/src/arm/frames-arm.cc
index b0fa13a5a1..6fde4b73c0 100644
--- a/deps/v8/src/arm/frames-arm.cc
+++ b/deps/v8/src/arm/frames-arm.cc
@@ -54,24 +54,23 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
if (fp == 0) return NONE;
// Compute frame type and stack pointer.
Address sp = fp + ExitFrameConstants::kSPDisplacement;
- const int offset = ExitFrameConstants::kCodeOffset;
- Object* code = Memory::Object_at(fp + offset);
- bool is_debug_exit = code->IsSmi();
- if (is_debug_exit) {
+ Type type;
+ if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+ type = EXIT_DEBUG;
sp -= kNumJSCallerSaved * kPointerSize;
+ } else {
+ type = EXIT;
}
// Fill in the state.
state->sp = sp;
state->fp = fp;
state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- return EXIT;
+ return type;
}
void ExitFrame::Iterate(ObjectVisitor* v) const {
- v->VisitPointer(&code_slot());
- // The arguments are traversed as part of the expression stack of
- // the calling frame.
+ // Do nothing
}
diff --git a/deps/v8/src/arm/frames-arm.h b/deps/v8/src/arm/frames-arm.h
index 4924c1aeb9..0874c09274 100644
--- a/deps/v8/src/arm/frames-arm.h
+++ b/deps/v8/src/arm/frames-arm.h
@@ -100,7 +100,7 @@ class ExitFrameConstants : public AllStatic {
static const int kSPDisplacement = -1 * kPointerSize;
// The debug marker is just above the frame pointer.
- static const int kCodeOffset = -1 * kPointerSize;
+ static const int kDebugMarkOffset = -1 * kPointerSize;
static const int kSavedRegistersOffset = 0 * kPointerSize;
diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc
index dc73bad93f..45c6540eeb 100644
--- a/deps/v8/src/arm/macro-assembler-arm.cc
+++ b/deps/v8/src/arm/macro-assembler-arm.cc
@@ -274,7 +274,9 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
}
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
+ ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
// Compute the argv pointer and keep it in a callee-saved register.
// r0 is argc.
add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
@@ -296,11 +298,8 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
mov(fp, Operand(sp)); // setup new frame pointer
- if (mode == ExitFrame::MODE_DEBUG) {
- mov(ip, Operand(Smi::FromInt(0)));
- } else {
- mov(ip, Operand(CodeObject()));
- }
+ // Push debug marker.
+ mov(ip, Operand(type == StackFrame::EXIT_DEBUG ? 1 : 0));
push(ip);
// Save the frame pointer and the context in top.
@@ -317,7 +316,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory
// location. This is needed to allow nested break points.
- if (mode == ExitFrame::MODE_DEBUG) {
+ if (type == StackFrame::EXIT_DEBUG) {
// Use sp as base to push.
CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
}
@@ -349,14 +348,14 @@ void MacroAssembler::AlignStack(int offset) {
}
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points.
- if (mode == ExitFrame::MODE_DEBUG) {
+ if (type == StackFrame::EXIT_DEBUG) {
// This code intentionally clobbers r2 and r3.
const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
- const int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
+ const int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
add(r3, fp, Operand(kOffset));
CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
}
diff --git a/deps/v8/src/arm/macro-assembler-arm.h b/deps/v8/src/arm/macro-assembler-arm.h
index 6dc2b7ae89..e37bb5e1c2 100644
--- a/deps/v8/src/arm/macro-assembler-arm.h
+++ b/deps/v8/src/arm/macro-assembler-arm.h
@@ -87,14 +87,14 @@ class MacroAssembler: public Assembler {
void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
- // Enter specific kind of exit frame; either normal or debug mode.
- // Expects the number of arguments in register r0 and
+ // Enter specific kind of exit frame; either EXIT or
+ // EXIT_DEBUG. Expects the number of arguments in register r0 and
// the builtin function to call in register r1. Exits with argc in
// r4, argv in r6, and and the builtin function to call in r5.
- void EnterExitFrame(ExitFrame::Mode mode);
+ void EnterExitFrame(StackFrame::Type type);
// Leave the current exit frame. Expects the return value in r0.
- void LeaveExitFrame(ExitFrame::Mode mode);
+ void LeaveExitFrame(StackFrame::Type type);
// Align the stack by optionally pushing a Smi zero.
void AlignStack(int offset);
diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc
index 34346a9105..34595f83ff 100644
--- a/deps/v8/src/assembler.cc
+++ b/deps/v8/src/assembler.cc
@@ -522,10 +522,6 @@ ExternalReference::ExternalReference(Builtins::CFunctionId id)
: address_(Redirect(Builtins::c_function_address(id))) {}
-ExternalReference::ExternalReference(ApiFunction* fun)
- : address_(Redirect(fun->address())) {}
-
-
ExternalReference::ExternalReference(Builtins::Name name)
: address_(Builtins::builtin_address(name)) {}
@@ -612,27 +608,6 @@ ExternalReference ExternalReference::new_space_allocation_limit_address() {
return ExternalReference(Heap::NewSpaceAllocationLimitAddress());
}
-
-ExternalReference ExternalReference::handle_scope_extensions_address() {
- return ExternalReference(HandleScope::current_extensions_address());
-}
-
-
-ExternalReference ExternalReference::handle_scope_next_address() {
- return ExternalReference(HandleScope::current_next_address());
-}
-
-
-ExternalReference ExternalReference::handle_scope_limit_address() {
- return ExternalReference(HandleScope::current_limit_address());
-}
-
-
-ExternalReference ExternalReference::scheduled_exception_address() {
- return ExternalReference(Top::scheduled_exception_address());
-}
-
-
#ifdef V8_NATIVE_REGEXP
ExternalReference ExternalReference::re_check_stack_guard_state() {
diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h
index 311dadd53c..21a66dd501 100644
--- a/deps/v8/src/assembler.h
+++ b/deps/v8/src/assembler.h
@@ -373,8 +373,6 @@ class ExternalReference BASE_EMBEDDED {
public:
explicit ExternalReference(Builtins::CFunctionId id);
- explicit ExternalReference(ApiFunction* ptr);
-
explicit ExternalReference(Builtins::Name name);
explicit ExternalReference(Runtime::FunctionId id);
@@ -424,12 +422,6 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference double_fp_operation(Token::Value operation);
static ExternalReference compare_doubles();
- static ExternalReference handle_scope_extensions_address();
- static ExternalReference handle_scope_next_address();
- static ExternalReference handle_scope_limit_address();
-
- static ExternalReference scheduled_exception_address();
-
Address address() const {return reinterpret_cast<Address>(address_);}
#ifdef ENABLE_DEBUGGER_SUPPORT
diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h
index 9b7d9ddb05..be64dcb3c6 100644
--- a/deps/v8/src/ast.h
+++ b/deps/v8/src/ast.h
@@ -162,7 +162,7 @@ class Statement: public AstNode {
class Expression: public AstNode {
public:
- Expression() : location_(Location::Temporary()) {}
+ Expression() : location_(Location::Uninitialized()) {}
virtual Expression* AsExpression() { return this; }
diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc
index 7a2f859459..73ff0115f2 100644
--- a/deps/v8/src/code-stubs.cc
+++ b/deps/v8/src/code-stubs.cc
@@ -36,27 +36,10 @@ namespace v8 {
namespace internal {
Handle<Code> CodeStub::GetCode() {
- bool custom_cache = has_custom_cache();
-
- int index = 0;
- uint32_t key = 0;
- if (custom_cache) {
- Code* cached;
- if (GetCustomCache(&cached)) {
- return Handle<Code>(cached);
- } else {
- index = NumberDictionary::kNotFound;
- }
- } else {
- key = GetKey();
- index = Heap::code_stubs()->FindEntry(key);
- if (index != NumberDictionary::kNotFound)
- return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
- }
-
- Code* result;
- {
- v8::HandleScope scope;
+ uint32_t key = GetKey();
+ int index = Heap::code_stubs()->FindEntry(key);
+ if (index == NumberDictionary::kNotFound) {
+ HandleScope scope;
// Update the static counter each time a new code stub is generated.
Counters::code_stubs.Increment();
@@ -96,21 +79,18 @@ Handle<Code> CodeStub::GetCode() {
}
#endif
- if (custom_cache) {
- SetCustomCache(*code);
- } else {
- // Update the dictionary and the root in Heap.
- Handle<NumberDictionary> dict =
- Factory::DictionaryAtNumberPut(
- Handle<NumberDictionary>(Heap::code_stubs()),
- key,
- code);
- Heap::public_set_code_stubs(*dict);
- }
- result = *code;
+ // Update the dictionary and the root in Heap.
+ Handle<NumberDictionary> dict =
+ Factory::DictionaryAtNumberPut(
+ Handle<NumberDictionary>(Heap::code_stubs()),
+ key,
+ code);
+ Heap::public_set_code_stubs(*dict);
+ index = Heap::code_stubs()->FindEntry(key);
}
+ ASSERT(index != NumberDictionary::kNotFound);
- return Handle<Code>(result);
+ return Handle<Code>(Code::cast(Heap::code_stubs()->ValueAt(index)));
}
diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h
index 63461bc0c0..121140d1ba 100644
--- a/deps/v8/src/code-stubs.h
+++ b/deps/v8/src/code-stubs.h
@@ -75,7 +75,6 @@ class CodeStub BASE_EMBEDDED {
#define DEF_ENUM(name) name,
CODE_STUB_LIST(DEF_ENUM)
#undef DEF_ENUM
- NoCache, // marker for stubs that do custom caching
NUMBER_OF_IDS
};
@@ -92,12 +91,6 @@ class CodeStub BASE_EMBEDDED {
virtual ~CodeStub() {}
- // Override these methods to provide a custom caching mechanism for
- // an individual type of code stub.
- virtual bool GetCustomCache(Code** code_out) { return false; }
- virtual void SetCustomCache(Code* value) { }
- virtual bool has_custom_cache() { return false; }
-
protected:
static const int kMajorBits = 5;
static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc
index f2788a8838..28c0ba5f9e 100644
--- a/deps/v8/src/codegen.cc
+++ b/deps/v8/src/codegen.cc
@@ -551,20 +551,4 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
}
-bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
- Object* cache = info()->load_stub_cache();
- if (cache->IsUndefined()) {
- return false;
- } else {
- *code_out = Code::cast(cache);
- return true;
- }
-}
-
-
-void ApiGetterEntryStub::SetCustomCache(Code* value) {
- info()->set_load_stub_cache(value);
-}
-
-
} } // namespace v8::internal
diff --git a/deps/v8/src/codegen.h b/deps/v8/src/codegen.h
index fc4a53b2e7..8c1b733675 100644
--- a/deps/v8/src/codegen.h
+++ b/deps/v8/src/codegen.h
@@ -301,7 +301,7 @@ class CEntryStub : public CodeStub {
Label* throw_normal_exception,
Label* throw_termination_exception,
Label* throw_out_of_memory_exception,
- ExitFrame::Mode mode,
+ StackFrame::Type frame_type,
bool do_gc,
bool always_allocate_scope);
void GenerateThrowTOS(MacroAssembler* masm);
@@ -320,32 +320,6 @@ class CEntryStub : public CodeStub {
};
-class ApiGetterEntryStub : public CodeStub {
- public:
- ApiGetterEntryStub(Handle<AccessorInfo> info,
- ApiFunction* fun)
- : info_(info),
- fun_(fun) { }
- void Generate(MacroAssembler* masm);
- virtual bool has_custom_cache() { return true; }
- virtual bool GetCustomCache(Code** code_out);
- virtual void SetCustomCache(Code* value);
-
- static const int kStackSpace = 6;
- static const int kArgc = 4;
- private:
- Handle<AccessorInfo> info() { return info_; }
- ApiFunction* fun() { return fun_; }
- Major MajorKey() { return NoCache; }
- int MinorKey() { return 0; }
- const char* GetName() { return "ApiEntryStub"; }
- // The accessor info associated with the function.
- Handle<AccessorInfo> info_;
- // The function to be called.
- ApiFunction* fun_;
-};
-
-
class CEntryDebugBreakStub : public CEntryStub {
public:
CEntryDebugBreakStub() : CEntryStub(1) { }
diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc
index bad209e138..129f1aac15 100644
--- a/deps/v8/src/compiler.cc
+++ b/deps/v8/src/compiler.cc
@@ -48,7 +48,7 @@ class CodeGenSelector: public AstVisitor {
CodeGenSelector()
: has_supported_syntax_(true),
- location_(Location::Nowhere()) {
+ location_(Location::Uninitialized()) {
}
CodeGenTag Select(FunctionLiteral* fun);
@@ -514,11 +514,11 @@ void CodeGenSelector::VisitStatements(ZoneList<Statement*>* stmts) {
void CodeGenSelector::VisitAsEffect(Expression* expr) {
- if (location_.is_nowhere()) {
+ if (location_.is_effect()) {
Visit(expr);
} else {
Location saved = location_;
- location_ = Location::Nowhere();
+ location_ = Location::Effect();
Visit(expr);
location_ = saved;
}
@@ -526,11 +526,11 @@ void CodeGenSelector::VisitAsEffect(Expression* expr) {
void CodeGenSelector::VisitAsValue(Expression* expr) {
- if (location_.is_temporary()) {
+ if (location_.is_value()) {
Visit(expr);
} else {
Location saved = location_;
- location_ = Location::Temporary();
+ location_ = Location::Value();
Visit(expr);
location_ = saved;
}
@@ -849,6 +849,12 @@ void CodeGenSelector::VisitCountOperation(CountOperation* expr) {
void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
+ case Token::COMMA:
+ VisitAsEffect(expr->left());
+ CHECK_BAILOUT;
+ Visit(expr->right()); // Location is the same as the parent location.
+ break;
+
case Token::OR:
VisitAsValue(expr->left());
CHECK_BAILOUT;
@@ -857,6 +863,22 @@ void CodeGenSelector::VisitBinaryOperation(BinaryOperation* expr) {
Visit(expr->right());
break;
+ case Token::ADD:
+ case Token::SUB:
+ case Token::DIV:
+ case Token::MOD:
+ case Token::MUL:
+ case Token::BIT_OR:
+ case Token::BIT_AND:
+ case Token::BIT_XOR:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::SAR:
+ VisitAsValue(expr->left());
+ CHECK_BAILOUT;
+ VisitAsValue(expr->right());
+ break;
+
default:
BAILOUT("Unsupported binary operation");
}
diff --git a/deps/v8/src/fast-codegen.cc b/deps/v8/src/fast-codegen.cc
index 8655e97a86..2f6a27a5e8 100644
--- a/deps/v8/src/fast-codegen.cc
+++ b/deps/v8/src/fast-codegen.cc
@@ -71,30 +71,15 @@ int FastCodeGenerator::SlotOffset(Slot* slot) {
}
-void FastCodeGenerator::Move(Location destination, Location source) {
- switch (destination.type()) {
- case Location::NOWHERE:
- break;
-
- case Location::TEMP:
- switch (source.type()) {
- case Location::NOWHERE:
- UNREACHABLE();
- case Location::TEMP:
- break;
- }
- break;
- }
-}
-
-
// All platform macro assemblers in {ia32,x64,arm} have a push(Register)
// function.
void FastCodeGenerator::Move(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
masm_->push(source);
break;
}
@@ -105,9 +90,10 @@ void FastCodeGenerator::Move(Location destination, Register source) {
// function.
void FastCodeGenerator::Move(Register destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized: // Fall through.
+ case Location::kEffect:
UNREACHABLE();
- case Location::TEMP:
+ case Location::kValue:
masm_->pop(destination);
}
}
diff --git a/deps/v8/src/fast-codegen.h b/deps/v8/src/fast-codegen.h
index a718157b35..31bb41c4da 100644
--- a/deps/v8/src/fast-codegen.h
+++ b/deps/v8/src/fast-codegen.h
@@ -51,8 +51,6 @@ class FastCodeGenerator: public AstVisitor {
private:
int SlotOffset(Slot* slot);
- void Move(Location destination, Location source);
-
void Move(Location destination, Register source);
void Move(Location destination, Slot* source);
void Move(Location destination, Literal* source);
@@ -78,6 +76,9 @@ class FastCodeGenerator: public AstVisitor {
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
+ // Handles the shortcutted logical binary operations in VisitBinaryOperation.
+ void EmitLogicalOperation(BinaryOperation* expr);
+
MacroAssembler* masm_;
FunctionLiteral* function_;
Handle<Script> script_;
diff --git a/deps/v8/src/frames.cc b/deps/v8/src/frames.cc
index d7302dea3d..5cd83324c6 100644
--- a/deps/v8/src/frames.cc
+++ b/deps/v8/src/frames.cc
@@ -393,19 +393,8 @@ Code* EntryConstructFrame::code() const {
}
-Object*& ExitFrame::code_slot() const {
- const int offset = ExitFrameConstants::kCodeOffset;
- return Memory::Object_at(fp() + offset);
-}
-
-
Code* ExitFrame::code() const {
- Object* code = code_slot();
- if (code->IsSmi()) {
- return Heap::c_entry_debug_break_code();
- } else {
- return Code::cast(code);
- }
+ return Heap::c_entry_code();
}
@@ -423,6 +412,11 @@ Address ExitFrame::GetCallerStackPointer() const {
}
+Code* ExitDebugFrame::code() const {
+ return Heap::c_entry_debug_break_code();
+}
+
+
Address StandardFrame::GetExpressionAddress(int n) const {
const int offset = StandardFrameConstants::kExpressionsOffset;
return fp() + offset - n * kPointerSize;
diff --git a/deps/v8/src/frames.h b/deps/v8/src/frames.h
index 024065abf7..768196d3c6 100644
--- a/deps/v8/src/frames.h
+++ b/deps/v8/src/frames.h
@@ -93,6 +93,7 @@ class StackHandler BASE_EMBEDDED {
V(ENTRY, EntryFrame) \
V(ENTRY_CONSTRUCT, EntryConstructFrame) \
V(EXIT, ExitFrame) \
+ V(EXIT_DEBUG, ExitDebugFrame) \
V(JAVA_SCRIPT, JavaScriptFrame) \
V(INTERNAL, InternalFrame) \
V(CONSTRUCT, ConstructFrame) \
@@ -118,6 +119,7 @@ class StackFrame BASE_EMBEDDED {
bool is_entry() const { return type() == ENTRY; }
bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
bool is_exit() const { return type() == EXIT; }
+ bool is_exit_debug() const { return type() == EXIT_DEBUG; }
bool is_java_script() const { return type() == JAVA_SCRIPT; }
bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
bool is_internal() const { return type() == INTERNAL; }
@@ -258,13 +260,10 @@ class EntryConstructFrame: public EntryFrame {
// Exit frames are used to exit JavaScript execution and go to C.
class ExitFrame: public StackFrame {
public:
- enum Mode { MODE_NORMAL, MODE_DEBUG };
virtual Type type() const { return EXIT; }
virtual Code* code() const;
- Object*& code_slot() const;
-
// Garbage collection support.
virtual void Iterate(ObjectVisitor* v) const;
@@ -290,6 +289,26 @@ class ExitFrame: public StackFrame {
};
+class ExitDebugFrame: public ExitFrame {
+ public:
+ virtual Type type() const { return EXIT_DEBUG; }
+
+ virtual Code* code() const;
+
+ static ExitDebugFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_exit_debug());
+ return static_cast<ExitDebugFrame*>(frame);
+ }
+
+ protected:
+ explicit ExitDebugFrame(StackFrameIterator* iterator)
+ : ExitFrame(iterator) { }
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
class StandardFrame: public StackFrame {
public:
// Testers.
diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h
index ae10b72de7..fbb648f5b1 100644
--- a/deps/v8/src/globals.h
+++ b/deps/v8/src/globals.h
@@ -103,10 +103,6 @@ typedef byte* Address;
#define V8PRIxPTR "lx"
#endif
-#if defined(__APPLE__) && defined(__MACH__)
-#define USING_MAC_ABI
-#endif
-
// Code-point values in Unicode 4.0 are 21 bits wide.
typedef uint16_t uc16;
typedef int32_t uc32;
diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc
index 275fe6a7c1..b764334e83 100644
--- a/deps/v8/src/handles.cc
+++ b/deps/v8/src/handles.cc
@@ -105,21 +105,6 @@ void HandleScope::ZapRange(Object** start, Object** end) {
}
-Address HandleScope::current_extensions_address() {
- return reinterpret_cast<Address>(&current_.extensions);
-}
-
-
-Address HandleScope::current_next_address() {
- return reinterpret_cast<Address>(&current_.next);
-}
-
-
-Address HandleScope::current_limit_address() {
- return reinterpret_cast<Address>(&current_.limit);
-}
-
-
Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray> content,
Handle<JSArray> array) {
CALL_HEAP_FUNCTION(content->AddKeysFromJSArray(*array), FixedArray);
diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h
index d3e9b788b5..5d574657c5 100644
--- a/deps/v8/src/handles.h
+++ b/deps/v8/src/handles.h
@@ -133,13 +133,6 @@ class HandleScope {
return result;
}
- // Deallocates any extensions used by the current scope.
- static void DeleteExtensions();
-
- static Address current_extensions_address();
- static Address current_next_address();
- static Address current_limit_address();
-
private:
// Prevent heap allocation or illegal handle scopes.
HandleScope(const HandleScope&);
@@ -173,6 +166,9 @@ class HandleScope {
// Extend the handle scope making room for more handles.
static internal::Object** Extend();
+ // Deallocates any extensions used by the current scope.
+ static void DeleteExtensions();
+
// Zaps the handles in the half-open interval [start, end).
static void ZapRange(internal::Object** start, internal::Object** end);
diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc
index 8e8ff2e0b1..4ac5527699 100644
--- a/deps/v8/src/ia32/codegen-ia32.cc
+++ b/deps/v8/src/ia32/codegen-ia32.cc
@@ -7707,84 +7707,11 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
}
-// If true, a Handle<T> passed by value is passed and returned by
-// using the location_ field directly. If false, it is passed and
-// returned as a pointer to a handle.
-#ifdef USING_MAC_ABI
-static const bool kPassHandlesDirectly = true;
-#else
-static const bool kPassHandlesDirectly = false;
-#endif
-
-
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
- Label get_result;
- Label prologue;
- Label promote_scheduled_exception;
- __ EnterApiExitFrame(ExitFrame::MODE_NORMAL, kStackSpace, kArgc);
- ASSERT_EQ(kArgc, 4);
- if (kPassHandlesDirectly) {
- // When handles as passed directly we don't have to allocate extra
- // space for and pass an out parameter.
- __ mov(Operand(esp, 0 * kPointerSize), ebx); // name.
- __ mov(Operand(esp, 1 * kPointerSize), eax); // arguments pointer.
- } else {
- // The function expects three arguments to be passed but we allocate
- // four to get space for the output cell. The argument slots are filled
- // as follows:
- //
- // 3: output cell
- // 2: arguments pointer
- // 1: name
- // 0: pointer to the output cell
- //
- // Note that this is one more "argument" than the function expects
- // so the out cell will have to be popped explicitly after returning
- // from the function.
- __ mov(Operand(esp, 1 * kPointerSize), ebx); // name.
- __ mov(Operand(esp, 2 * kPointerSize), eax); // arguments pointer.
- __ mov(ebx, esp);
- __ add(Operand(ebx), Immediate(3 * kPointerSize));
- __ mov(Operand(esp, 0 * kPointerSize), ebx); // output
- __ mov(Operand(esp, 3 * kPointerSize), Immediate(0)); // out cell.
- }
- // Call the api function!
- __ call(fun()->address(), RelocInfo::RUNTIME_ENTRY);
- // Check if the function scheduled an exception.
- ExternalReference scheduled_exception_address =
- ExternalReference::scheduled_exception_address();
- __ cmp(Operand::StaticVariable(scheduled_exception_address),
- Immediate(Factory::the_hole_value()));
- __ j(not_equal, &promote_scheduled_exception, not_taken);
- if (!kPassHandlesDirectly) {
- // The returned value is a pointer to the handle holding the result.
- // Dereference this to get to the location.
- __ mov(eax, Operand(eax, 0));
- }
- // Check if the result handle holds 0
- __ test(eax, Operand(eax));
- __ j(not_zero, &get_result, taken);
- // It was zero; the result is undefined.
- __ mov(eax, Factory::undefined_value());
- __ jmp(&prologue);
- // It was non-zero. Dereference to get the result value.
- __ bind(&get_result);
- __ mov(eax, Operand(eax, 0));
- __ bind(&prologue);
- __ LeaveExitFrame(ExitFrame::MODE_NORMAL);
- __ ret(0);
- __ bind(&promote_scheduled_exception);
- __ TailCallRuntime(ExternalReference(Runtime::kPromoteScheduledException),
- 0,
- 1);
-}
-
-
void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
Label* throw_termination_exception,
Label* throw_out_of_memory_exception,
- ExitFrame::Mode mode,
+ StackFrame::Type frame_type,
bool do_gc,
bool always_allocate_scope) {
// eax: result parameter for PerformGC, if any
@@ -7834,7 +7761,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ j(zero, &failure_returned, not_taken);
// Exit the JavaScript to C++ exit frame.
- __ LeaveExitFrame(mode);
+ __ LeaveExitFrame(frame_type);
__ ret(0);
// Handling of failure.
@@ -7933,12 +7860,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// of a proper result. The builtin entry handles this by performing
// a garbage collection and retrying the builtin (twice).
- ExitFrame::Mode mode = is_debug_break
- ? ExitFrame::MODE_DEBUG
- : ExitFrame::MODE_NORMAL;
+ StackFrame::Type frame_type = is_debug_break ?
+ StackFrame::EXIT_DEBUG :
+ StackFrame::EXIT;
// Enter the exit frame that transitions from JavaScript to C++.
- __ EnterExitFrame(mode);
+ __ EnterExitFrame(frame_type);
// eax: result parameter for PerformGC, if any (setup below)
// ebx: pointer to builtin function (C callee-saved)
@@ -7956,7 +7883,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
false,
false);
@@ -7965,7 +7892,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
true,
false);
@@ -7976,7 +7903,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
true,
true);
diff --git a/deps/v8/src/ia32/fast-codegen-ia32.cc b/deps/v8/src/ia32/fast-codegen-ia32.cc
index 0d661c3b67..247f124962 100644
--- a/deps/v8/src/ia32/fast-codegen-ia32.cc
+++ b/deps/v8/src/ia32/fast-codegen-ia32.cc
@@ -110,9 +110,11 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
__ push(Operand(ebp, SlotOffset(source)));
break;
}
@@ -121,9 +123,11 @@ void FastCodeGenerator::Move(Location destination, Slot* source) {
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
__ push(Immediate(expr->handle()));
break;
}
@@ -132,9 +136,10 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) {
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized: // Fall through.
+ case Location::kEffect:
UNREACHABLE();
- case Location::TEMP:
+ case Location::kValue:
__ pop(Operand(ebp, SlotOffset(destination)));
break;
}
@@ -143,10 +148,12 @@ void FastCodeGenerator::Move(Slot* destination, Location source) {
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
__ add(Operand(esp), Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::kValue:
__ mov(Operand(esp, 0), source);
break;
}
@@ -231,6 +238,33 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ Comment cmnt(masm_, "[ RegExp Literal");
+ Label done;
+ // Registers will be used as follows:
+ // edi = JS function.
+ // ebx = literals array.
+ // eax = regexp literal.
+ __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+ __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
+ int literal_offset =
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+ __ mov(eax, FieldOperand(ebx, literal_offset));
+ __ cmp(eax, Factory::undefined_value());
+ __ j(not_equal, &done);
+ // Create regexp literal using runtime function
+ // Result will be in eax.
+ __ push(ebx);
+ __ push(Immediate(Smi::FromInt(expr->literal_index())));
+ __ push(Immediate(expr->pattern()));
+ __ push(Immediate(expr->flags()));
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+ // Label done:
+ __ bind(&done);
+ Move(expr->location(), eax);
+}
+
+
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
Label exists;
@@ -295,9 +329,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
__ push(eax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kSetProperty, 3);
__ mov(eax, Operand(esp, 0)); // Restore result into eax.
break;
@@ -305,12 +339,12 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
__ push(eax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
__ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0)));
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ mov(eax, Operand(esp, 0)); // Restore result into eax.
break;
@@ -318,43 +352,18 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::kValue:
if (!result_saved) __ push(eax);
break;
}
}
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
- Comment cmnt(masm_, "[ RegExp Literal");
- Label done;
- // Registers will be used as follows:
- // edi = JS function.
- // ebx = literals array.
- // eax = regexp literal.
- __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
- __ mov(ebx, FieldOperand(edi, JSFunction::kLiteralsOffset));
- int literal_offset =
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
- __ mov(eax, FieldOperand(ebx, literal_offset));
- __ cmp(eax, Factory::undefined_value());
- __ j(not_equal, &done);
- // Create regexp literal using runtime function
- // Result will be in eax.
- __ push(ebx);
- __ push(Immediate(Smi::FromInt(expr->literal_index())));
- __ push(Immediate(expr->pattern()));
- __ push(Immediate(expr->flags()));
- __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- // Label done:
- __ bind(&done);
- Move(expr->location(), eax);
-}
-
-
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
Label make_clone;
@@ -403,7 +412,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
result_saved = true;
}
Visit(subexpr);
- ASSERT(subexpr->location().is_temporary());
+ ASSERT(subexpr->location().is_value());
// Store the subexpression value in the array's elements.
__ pop(eax); // Subexpression value.
@@ -417,10 +426,12 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
if (result_saved) __ add(Operand(esp), Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::kValue:
if (!result_saved) __ push(eax);
break;
}
@@ -446,7 +457,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
if (rhs->AsLiteral() != NULL) {
__ mov(eax, rhs->AsLiteral()->handle());
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
__ pop(eax);
}
@@ -467,14 +478,16 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ mov(Operand(ebp, SlotOffset(var->slot())), eax);
Move(expr->location(), eax);
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
break;
- case Location::TEMP:
+ case Location::kValue:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ mov(eax, Operand(esp, 0));
@@ -519,10 +532,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
__ add(Operand(esp), Immediate(kPointerSize));
}
switch (expr->location().type()) {
- case Location::TEMP:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kValue:
__ mov(Operand(esp, 0), eax);
break;
- case Location::NOWHERE:
+ case Location::kEffect:
__ add(Operand(esp), Immediate(kPointerSize));
break;
}
@@ -542,7 +557,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
// Record source position for debugger
SetSourcePosition(expr->position());
@@ -564,7 +579,7 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
// arguments.
// Push function on the stack.
Visit(node->expression());
- ASSERT(node->expression()->location().is_temporary());
+ ASSERT(node->expression()->location().is_value());
// Push global object (receiver).
__ push(CodeGenerator::GlobalObject());
@@ -574,8 +589,8 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
- // If location is temporary, it is already on the stack,
+ ASSERT(args->at(i)->location().is_value());
+ // If location is value, it is already on the stack,
// so nothing to do here.
}
@@ -607,7 +622,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
__ CallRuntime(function, arg_count);
@@ -616,13 +631,64 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
- // Compile a short-circuited boolean or operation in a non-test
- // context.
- ASSERT(expr->op() == Token::OR);
- // Compile (e0 || e1) as if it were
- // (let (temp = e0) temp ? temp : e1).
+ switch (expr->op()) {
+ case Token::COMMA:
+ ASSERT(expr->left()->location().is_effect());
+ ASSERT_EQ(expr->right()->location().type(), expr->location().type());
+ Visit(expr->left());
+ Visit(expr->right());
+ break;
+
+ case Token::OR:
+ case Token::AND:
+ EmitLogicalOperation(expr);
+ break;
+
+ case Token::ADD:
+ case Token::SUB:
+ case Token::DIV:
+ case Token::MOD:
+ case Token::MUL:
+ case Token::BIT_OR:
+ case Token::BIT_AND:
+ case Token::BIT_XOR:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::SAR: {
+ ASSERT(expr->left()->location().is_value());
+ ASSERT(expr->right()->location().is_value());
+
+ Visit(expr->left());
+ Visit(expr->right());
+ GenericBinaryOpStub stub(expr->op(),
+ NO_OVERWRITE,
+ NO_GENERIC_BINARY_FLAGS);
+ __ CallStub(&stub);
+ Move(expr->location(), eax);
+
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
+ // Compile a short-circuited boolean operation in a non-test context.
+
+ // Compile (e0 || e1) or (e0 && e1) as if it were
+ // (let (temp = e0) temp [or !temp, for &&] ? temp : e1).
Label eval_right, done;
+ Label *left_true, *left_false; // Where to branch to if lhs has that value.
+ if (expr->op() == Token::OR) {
+ left_true = &done;
+ left_false = &eval_right;
+ } else {
+ left_true = &eval_right;
+ left_false = &done;
+ }
Location destination = expr->location();
Expression* left = expr->left();
Expression* right = expr->right();
@@ -635,17 +701,19 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
// need it as the value of the whole expression.
if (left->AsLiteral() != NULL) {
__ mov(eax, left->AsLiteral()->handle());
- if (destination.is_temporary()) __ push(eax);
+ if (destination.is_value()) __ push(eax);
} else {
Visit(left);
- ASSERT(left->location().is_temporary());
+ ASSERT(left->location().is_value());
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
// Pop the left-hand value into eax because we will not need it as the
// final result.
__ pop(eax);
break;
- case Location::TEMP:
+ case Location::kValue:
// Copy the left-hand value into eax because we may need it as the
// final result.
__ mov(eax, Operand(esp, 0));
@@ -653,40 +721,40 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
}
}
// The left-hand value is in eax. It is also on the stack iff the
- // destination location is temporary.
+ // destination location is value.
// Perform fast checks assumed by the stub.
__ cmp(eax, Factory::undefined_value()); // The undefined value is false.
- __ j(equal, &eval_right);
+ __ j(equal, left_false);
__ cmp(eax, Factory::true_value()); // True is true.
- __ j(equal, &done);
+ __ j(equal, left_true);
__ cmp(eax, Factory::false_value()); // False is false.
- __ j(equal, &eval_right);
+ __ j(equal, left_false);
ASSERT(kSmiTag == 0);
__ test(eax, Operand(eax)); // The smi zero is false.
- __ j(zero, &eval_right);
+ __ j(zero, left_false);
__ test(eax, Immediate(kSmiTagMask)); // All other smis are true.
- __ j(zero, &done);
+ __ j(zero, left_true);
// Call the stub for all other cases.
__ push(eax);
ToBooleanStub stub;
__ CallStub(&stub);
__ test(eax, Operand(eax)); // The stub returns nonzero for true.
- __ j(not_zero, &done);
+ if (expr->op() == Token::OR) {
+ __ j(not_zero, &done);
+ } else {
+ __ j(zero, &done);
+ }
__ bind(&eval_right);
// Discard the left-hand value if present on the stack.
- if (destination.is_temporary()) {
+ if (destination.is_value()) {
__ add(Operand(esp), Immediate(kPointerSize));
}
// Save or discard the right-hand value as needed.
- if (right->AsLiteral() != NULL) {
- Move(destination, right->AsLiteral());
- } else {
- Visit(right);
- Move(destination, right->location());
- }
+ Visit(right);
+ ASSERT_EQ(destination.type(), right->location().type());
__ bind(&done);
}
diff --git a/deps/v8/src/ia32/frames-ia32.cc b/deps/v8/src/ia32/frames-ia32.cc
index 5c900bedd7..dea439f24b 100644
--- a/deps/v8/src/ia32/frames-ia32.cc
+++ b/deps/v8/src/ia32/frames-ia32.cc
@@ -56,14 +56,19 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
state->fp = fp;
state->sp = sp;
state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- return EXIT;
+ // Determine frame type.
+ if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+ return EXIT_DEBUG;
+ } else {
+ return EXIT;
+ }
}
void ExitFrame::Iterate(ObjectVisitor* v) const {
- v->VisitPointer(&code_slot());
- // The arguments are traversed as part of the expression stack of
- // the calling frame.
+ // Exit frames on IA-32 do not contain any pointers. The arguments
+ // are traversed as part of the expression stack of the calling
+ // frame.
}
diff --git a/deps/v8/src/ia32/frames-ia32.h b/deps/v8/src/ia32/frames-ia32.h
index c3fe6c748d..3a7c86bf73 100644
--- a/deps/v8/src/ia32/frames-ia32.h
+++ b/deps/v8/src/ia32/frames-ia32.h
@@ -76,7 +76,7 @@ class EntryFrameConstants : public AllStatic {
class ExitFrameConstants : public AllStatic {
public:
- static const int kCodeOffset = -2 * kPointerSize;
+ static const int kDebugMarkOffset = -2 * kPointerSize;
static const int kSPOffset = -1 * kPointerSize;
static const int kCallerFPOffset = 0 * kPointerSize;
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc
index 34d4fd5f6d..08c4c0c51b 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.cc
+++ b/deps/v8/src/ia32/macro-assembler-ia32.cc
@@ -355,7 +355,10 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
leave();
}
-void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) {
+
+void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
+ ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
// Setup the frame structure on the stack.
ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
ASSERT(ExitFrameConstants::kCallerPCOffset == +1 * kPointerSize);
@@ -366,24 +369,23 @@ void MacroAssembler::EnterExitFramePrologue(ExitFrame::Mode mode) {
// Reserve room for entry stack pointer and push the debug marker.
ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
push(Immediate(0)); // saved entry sp, patched before call
- if (mode == ExitFrame::MODE_DEBUG) {
- push(Immediate(0));
- } else {
- push(Immediate(CodeObject()));
- }
+ push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
// Save the frame pointer and the context in top.
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
ExternalReference context_address(Top::k_context_address);
mov(Operand::StaticVariable(c_entry_fp_address), ebp);
mov(Operand::StaticVariable(context_address), esi);
-}
-void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
+ // Setup argc and argv in callee-saved registers.
+ int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
+ mov(edi, Operand(eax));
+ lea(esi, Operand(ebp, eax, times_4, offset));
+
#ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory
// location. This is needed to allow nested break points.
- if (mode == ExitFrame::MODE_DEBUG) {
+ if (type == StackFrame::EXIT_DEBUG) {
// TODO(1243899): This should be symmetric to
// CopyRegistersFromStackToMemory() but it isn't! esp is assumed
// correct here, but computed for the other call. Very error
@@ -394,8 +396,8 @@ void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
}
#endif
- // Reserve space for arguments.
- sub(Operand(esp), Immediate(argc * kPointerSize));
+ // Reserve space for two arguments: argc and argv.
+ sub(Operand(esp), Immediate(2 * kPointerSize));
// Get the required frame alignment for the OS.
static const int kFrameAlignment = OS::ActivationFrameAlignment();
@@ -409,39 +411,15 @@ void MacroAssembler::EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc) {
}
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode) {
- EnterExitFramePrologue(mode);
-
- // Setup argc and argv in callee-saved registers.
- int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
- mov(edi, Operand(eax));
- lea(esi, Operand(ebp, eax, times_4, offset));
-
- EnterExitFrameEpilogue(mode, 2);
-}
-
-
-void MacroAssembler::EnterApiExitFrame(ExitFrame::Mode mode,
- int stack_space,
- int argc) {
- EnterExitFramePrologue(mode);
-
- int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
- lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset));
-
- EnterExitFrameEpilogue(mode, argc);
-}
-
-
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode) {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points.
- if (mode == ExitFrame::MODE_DEBUG) {
+ if (type == StackFrame::EXIT_DEBUG) {
// It's okay to clobber register ebx below because we don't need
// the function pointer after this.
const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
- int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
+ int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
lea(ebx, Operand(ebp, kOffset));
CopyRegistersFromStackToMemory(ebx, ecx, kJSCallerSaved);
}
@@ -953,48 +931,6 @@ void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
}
-void MacroAssembler::PushHandleScope(Register scratch) {
- // Push the number of extensions, smi-tagged so the gc will ignore it.
- ExternalReference extensions_address =
- ExternalReference::handle_scope_extensions_address();
- mov(scratch, Operand::StaticVariable(extensions_address));
- ASSERT_EQ(0, kSmiTag);
- shl(scratch, kSmiTagSize);
- push(scratch);
- mov(Operand::StaticVariable(extensions_address), Immediate(0));
- // Push next and limit pointers which will be wordsize aligned and
- // hence automatically smi tagged.
- ExternalReference next_address =
- ExternalReference::handle_scope_next_address();
- push(Operand::StaticVariable(next_address));
- ExternalReference limit_address =
- ExternalReference::handle_scope_limit_address();
- push(Operand::StaticVariable(limit_address));
-}
-
-
-void MacroAssembler::PopHandleScope(Register scratch) {
- ExternalReference extensions_address =
- ExternalReference::handle_scope_extensions_address();
- Label write_back;
- mov(scratch, Operand::StaticVariable(extensions_address));
- cmp(Operand(scratch), Immediate(0));
- j(equal, &write_back);
- CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
-
- bind(&write_back);
- ExternalReference limit_address =
- ExternalReference::handle_scope_limit_address();
- pop(Operand::StaticVariable(limit_address));
- ExternalReference next_address =
- ExternalReference::handle_scope_next_address();
- pop(Operand::StaticVariable(next_address));
- pop(scratch);
- shr(scratch, kSmiTagSize);
- mov(Operand::StaticVariable(extensions_address), scratch);
-}
-
-
void MacroAssembler::JumpToRuntime(const ExternalReference& ext) {
// Set the entry point and jump to the C entry runtime stub.
mov(ebx, Immediate(ext));
diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h
index 18d221c407..a0a242806b 100644
--- a/deps/v8/src/ia32/macro-assembler-ia32.h
+++ b/deps/v8/src/ia32/macro-assembler-ia32.h
@@ -77,18 +77,16 @@ class MacroAssembler: public Assembler {
void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
- // Enter specific kind of exit frame; either in normal or debug mode.
- // Expects the number of arguments in register eax and
+ // Enter specific kind of exit frame; either EXIT or
+ // EXIT_DEBUG. Expects the number of arguments in register eax and
// sets up the number of arguments in register edi and the pointer
// to the first argument in register esi.
- void EnterExitFrame(ExitFrame::Mode mode);
-
- void EnterApiExitFrame(ExitFrame::Mode mode, int stack_space, int argc);
+ void EnterExitFrame(StackFrame::Type type);
// Leave the current exit frame. Expects the return value in
// register eax:edx (untouched) and the pointer to the first
// argument in register esi.
- void LeaveExitFrame(ExitFrame::Mode mode);
+ void LeaveExitFrame(StackFrame::Type type);
// ---------------------------------------------------------------------------
@@ -271,9 +269,6 @@ class MacroAssembler: public Assembler {
int num_arguments,
int result_size);
- void PushHandleScope(Register scratch);
- void PopHandleScope(Register scratch);
-
// Jump to a runtime routine.
void JumpToRuntime(const ExternalReference& ext);
@@ -351,9 +346,6 @@ class MacroAssembler: public Assembler {
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);
- void EnterExitFramePrologue(ExitFrame::Mode mode);
- void EnterExitFrameEpilogue(ExitFrame::Mode mode, int argc);
-
// Allocation support helpers.
void LoadAllocationTopHelper(Register result,
Register result_end,
diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc
index 3e5fc04794..ca4e142101 100644
--- a/deps/v8/src/ia32/stub-cache-ia32.cc
+++ b/deps/v8/src/ia32/stub-cache-ia32.cc
@@ -776,39 +776,20 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
CheckPrototypes(object, receiver, holder,
scratch1, scratch2, name, miss);
- Handle<AccessorInfo> callback_handle(callback);
-
- Register other = reg.is(scratch1) ? scratch2 : scratch1;
- __ EnterInternalFrame();
- __ PushHandleScope(other);
- // Push the stack address where the list of arguments ends
- __ mov(other, esp);
- __ sub(Operand(other), Immediate(2 * kPointerSize));
- __ push(other);
+ // Push the arguments on the JS stack of the caller.
+ __ pop(scratch2); // remove return address
__ push(receiver); // receiver
__ push(reg); // holder
- __ mov(other, Immediate(callback_handle));
- __ push(other);
- __ push(FieldOperand(other, AccessorInfo::kDataOffset)); // data
+ __ mov(reg, Immediate(Handle<AccessorInfo>(callback))); // callback data
+ __ push(reg);
+ __ push(FieldOperand(reg, AccessorInfo::kDataOffset));
__ push(name_reg); // name
- // Save a pointer to where we pushed the arguments pointer.
- // This will be passed as the const Arguments& to the C++ callback.
- __ mov(eax, esp);
- __ add(Operand(eax), Immediate(5 * kPointerSize));
- __ mov(ebx, esp);
-
- // Do call through the api.
- ASSERT_EQ(6, ApiGetterEntryStub::kStackSpace);
- Address getter_address = v8::ToCData<Address>(callback->getter());
- ApiFunction fun(getter_address);
- ApiGetterEntryStub stub(callback_handle, &fun);
- __ CallStub(&stub);
+ __ push(scratch2); // restore return address
- Register tmp = other.is(eax) ? reg : other;
- __ PopHandleScope(tmp);
- __ LeaveInternalFrame();
-
- __ ret(0);
+ // Do tail-call to the runtime system.
+ ExternalReference load_callback_property =
+ ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+ __ TailCallRuntime(load_callback_property, 5, 1);
}
diff --git a/deps/v8/src/location.h b/deps/v8/src/location.h
index c4a77cb5d1..26b1a09e9c 100644
--- a/deps/v8/src/location.h
+++ b/deps/v8/src/location.h
@@ -35,13 +35,18 @@ namespace internal {
class Location BASE_EMBEDDED {
public:
- enum Type { NOWHERE, TEMP };
-
- static Location Temporary() { return Location(TEMP); }
- static Location Nowhere() { return Location(NOWHERE); }
-
- bool is_temporary() { return type_ == TEMP; }
- bool is_nowhere() { return type_ == NOWHERE; }
+ enum Type {
+ kUninitialized,
+ kEffect,
+ kValue
+ };
+
+ static Location Uninitialized() { return Location(kUninitialized); }
+ static Location Effect() { return Location(kEffect); }
+ static Location Value() { return Location(kValue); }
+
+ bool is_effect() { return type_ == kEffect; }
+ bool is_value() { return type_ == kValue; }
Type type() { return type_; }
diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc
index 10ad2941a3..01881346e1 100644
--- a/deps/v8/src/objects-debug.cc
+++ b/deps/v8/src/objects-debug.cc
@@ -979,7 +979,6 @@ void AccessorInfo::AccessorInfoVerify() {
VerifyPointer(name());
VerifyPointer(data());
VerifyPointer(flag());
- VerifyPointer(load_stub_cache());
}
void AccessorInfo::AccessorInfoPrint() {
diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h
index 5907a86f69..2350a35ba8 100644
--- a/deps/v8/src/objects-inl.h
+++ b/deps/v8/src/objects-inl.h
@@ -2436,7 +2436,6 @@ ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
ACCESSORS(AccessorInfo, data, Object, kDataOffset)
ACCESSORS(AccessorInfo, name, Object, kNameOffset)
ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
-ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)
ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h
index 61bdf44af1..89cbd44637 100644
--- a/deps/v8/src/objects.h
+++ b/deps/v8/src/objects.h
@@ -4719,7 +4719,6 @@ class AccessorInfo: public Struct {
DECL_ACCESSORS(data, Object)
DECL_ACCESSORS(name, Object)
DECL_ACCESSORS(flag, Smi)
- DECL_ACCESSORS(load_stub_cache, Object)
inline bool all_can_read();
inline void set_all_can_read(bool value);
@@ -4745,8 +4744,7 @@ class AccessorInfo: public Struct {
static const int kDataOffset = kSetterOffset + kPointerSize;
static const int kNameOffset = kDataOffset + kPointerSize;
static const int kFlagOffset = kNameOffset + kPointerSize;
- static const int kLoadStubCacheOffset = kFlagOffset + kPointerSize;
- static const int kSize = kLoadStubCacheOffset + kPointerSize;
+ static const int kSize = kFlagOffset + kPointerSize;
private:
// Bit positions in flag.
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc
index 76520e3aad..8fd62c986c 100644
--- a/deps/v8/src/runtime.cc
+++ b/deps/v8/src/runtime.cc
@@ -1357,9 +1357,8 @@ class ReplacementStringBuilder {
StringBuilderSubstringPosition::encode(from);
AddElement(Smi::FromInt(encoded_slice));
} else {
- // Otherwise encode as two smis.
- AddElement(Smi::FromInt(-length));
- AddElement(Smi::FromInt(from));
+ Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
+ AddElement(*slice);
}
IncrementCharacterCount(length);
}
@@ -3767,21 +3766,9 @@ static inline void StringBuilderConcatHelper(String* special,
for (int i = 0; i < array_length; i++) {
Object* element = fixed_array->get(i);
if (element->IsSmi()) {
- // Smi encoding of position and length.
int encoded_slice = Smi::cast(element)->value();
- int pos;
- int len;
- if (encoded_slice > 0) {
- // Position and length encoded in one smi.
- pos = StringBuilderSubstringPosition::decode(encoded_slice);
- len = StringBuilderSubstringLength::decode(encoded_slice);
- } else {
- // Position and length encoded in two smis.
- Object* obj = fixed_array->get(++i);
- ASSERT(obj->IsSmi());
- pos = Smi::cast(obj)->value();
- len = -encoded_slice;
- }
+ int pos = StringBuilderSubstringPosition::decode(encoded_slice);
+ int len = StringBuilderSubstringLength::decode(encoded_slice);
String::WriteToFlat(special,
sink + position,
pos,
@@ -3802,10 +3789,6 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
ASSERT(args.length() == 2);
CONVERT_CHECKED(JSArray, array, args[0]);
CONVERT_CHECKED(String, special, args[1]);
-
- // This assumption is used by the slice encoding in one or two smis.
- ASSERT(Smi::kMaxValue >= String::kMaxLength);
-
int special_length = special->length();
Object* smi_array_length = array->length();
if (!smi_array_length->IsSmi()) {
@@ -3833,29 +3816,13 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
for (int i = 0; i < array_length; i++) {
Object* elt = fixed_array->get(i);
if (elt->IsSmi()) {
- // Smi encoding of position and length.
int len = Smi::cast(elt)->value();
- if (len > 0) {
- // Position and length encoded in one smi.
- int pos = len >> 11;
- len &= 0x7ff;
- if (pos + len > special_length) {
- return Top::Throw(Heap::illegal_argument_symbol());
- }
- position += len;
- } else {
- // Position and length encoded in two smis.
- position += (-len);
- // Get the position and check that it is also a smi.
- i++;
- if (i >= array_length) {
- return Top::Throw(Heap::illegal_argument_symbol());
- }
- Object* pos = fixed_array->get(i);
- if (!pos->IsSmi()) {
- return Top::Throw(Heap::illegal_argument_symbol());
- }
+ int pos = len >> 11;
+ len &= 0x7ff;
+ if (pos + len > special_length) {
+ return Top::Throw(Heap::illegal_argument_symbol());
}
+ position += len;
} else if (elt->IsString()) {
String* element = String::cast(elt);
int element_length = element->length();
@@ -4830,12 +4797,6 @@ static Object* Runtime_ReThrow(Arguments args) {
}
-static Object* Runtime_PromoteScheduledException(Arguments args) {
- ASSERT_EQ(0, args.length());
- return Top::PromoteScheduledException();
-}
-
-
static Object* Runtime_ThrowReferenceError(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
@@ -7797,13 +7758,6 @@ static Object* Runtime_Abort(Arguments args) {
}
-static Object* Runtime_DeleteHandleScopeExtensions(Arguments args) {
- ASSERT(args.length() == 0);
- HandleScope::DeleteExtensions();
- return Heap::undefined_value();
-}
-
-
#ifdef DEBUG
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
// Exclude the code in release mode.
diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h
index a55ef25011..6b1ce480b5 100644
--- a/deps/v8/src/runtime.h
+++ b/deps/v8/src/runtime.h
@@ -234,7 +234,6 @@ namespace internal {
F(ReThrow, 1, 1) \
F(ThrowReferenceError, 1, 1) \
F(StackGuard, 1, 1) \
- F(PromoteScheduledException, 0, 1) \
\
/* Contexts */ \
F(NewContext, 1, 1) \
@@ -264,8 +263,6 @@ namespace internal {
F(Log, 2, 1) \
/* ES5 */ \
F(LocalKeys, 1, 1) \
- /* Handle scopes */ \
- F(DeleteHandleScopeExtensions, 0, 1) \
\
/* Pseudo functions - handled as macros by parser */ \
F(IS_VAR, 1, 1)
diff --git a/deps/v8/src/string.js b/deps/v8/src/string.js
index bb2ad4f2a0..d2d6e969df 100644
--- a/deps/v8/src/string.js
+++ b/deps/v8/src/string.js
@@ -1,4 +1,4 @@
-// Copyright 2006-2009 the V8 project authors. All rights reserved.
+// Copyright 2006-2008 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:
@@ -810,13 +810,10 @@ ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) {
var len = end - start;
if (len == 0) return;
var elements = this.elements;
- if (start < 0x80000 && len < 0x800) {
+ if (start >= 0 && len >= 0 && start < 0x80000 && len < 0x800) {
elements[elements.length] = (start << 11) + len;
} else {
- // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength,
- // so -len is a smi.
- elements[elements.length] = -len;
- elements[elements.length] = start;
+ elements[elements.length] = SubString(this.special_string, start, end);
}
}
diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc
index a399e4563e..e10dc61b2c 100644
--- a/deps/v8/src/stub-cache.cc
+++ b/deps/v8/src/stub-cache.cc
@@ -735,16 +735,11 @@ Handle<Code> ComputeCallMiss(int argc) {
Object* LoadCallbackProperty(Arguments args) {
- ASSERT(args[0]->IsJSObject());
- ASSERT(args[1]->IsJSObject());
AccessorInfo* callback = AccessorInfo::cast(args[2]);
Address getter_address = v8::ToCData<Address>(callback->getter());
v8::AccessorGetter fun = FUNCTION_CAST<v8::AccessorGetter>(getter_address);
ASSERT(fun != NULL);
- CustomArguments custom_args(callback->data(),
- JSObject::cast(args[0]),
- JSObject::cast(args[1]));
- v8::AccessorInfo info(custom_args.end());
+ v8::AccessorInfo info(args.arguments());
HandleScope scope;
v8::Handle<v8::Value> result;
{
diff --git a/deps/v8/src/top.h b/deps/v8/src/top.h
index 0f5aa27b2b..ae94f08e3c 100644
--- a/deps/v8/src/top.h
+++ b/deps/v8/src/top.h
@@ -170,10 +170,6 @@ class Top {
return &thread_local_.external_caught_exception_;
}
- static Object** scheduled_exception_address() {
- return &thread_local_.scheduled_exception_;
- }
-
static Object* scheduled_exception() {
ASSERT(has_scheduled_exception());
return thread_local_.scheduled_exception_;
diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc
index 7b8986cf28..944cd4e1c2 100644
--- a/deps/v8/src/version.cc
+++ b/deps/v8/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 1
#define MINOR_VERSION 3
-#define BUILD_NUMBER 17
+#define BUILD_NUMBER 18
#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 877cfdfb45..95f30d842d 100644
--- a/deps/v8/src/x64/codegen-x64.cc
+++ b/deps/v8/src/x64/codegen-x64.cc
@@ -6771,7 +6771,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
Label* throw_normal_exception,
Label* throw_termination_exception,
Label* throw_out_of_memory_exception,
- ExitFrame::Mode mode,
+ StackFrame::Type frame_type,
bool do_gc,
bool always_allocate_scope) {
// rax: result parameter for PerformGC, if any.
@@ -6854,7 +6854,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ j(zero, &failure_returned);
// Exit the JavaScript to C++ exit frame.
- __ LeaveExitFrame(mode, result_size_);
+ __ LeaveExitFrame(frame_type, result_size_);
__ ret(0);
// Handling of failure.
@@ -6984,12 +6984,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
// this by performing a garbage collection and retrying the
// builtin once.
- ExitFrame::Mode mode = is_debug_break ?
- ExitFrame::MODE_DEBUG :
- ExitFrame::MODE_NORMAL;
+ StackFrame::Type frame_type = is_debug_break ?
+ StackFrame::EXIT_DEBUG :
+ StackFrame::EXIT;
// Enter the exit frame that transitions from JavaScript to C++.
- __ EnterExitFrame(mode, result_size_);
+ __ EnterExitFrame(frame_type, result_size_);
// rax: Holds the context at this point, but should not be used.
// On entry to code generated by GenerateCore, it must hold
@@ -7012,7 +7012,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
false,
false);
@@ -7021,7 +7021,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
true,
false);
@@ -7032,7 +7032,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
&throw_normal_exception,
&throw_termination_exception,
&throw_out_of_memory_exception,
- mode,
+ frame_type,
true,
true);
@@ -7047,11 +7047,6 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
}
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
- UNREACHABLE();
-}
-
-
void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
Label invoke, exit;
#ifdef ENABLE_LOGGING_AND_PROFILING
diff --git a/deps/v8/src/x64/fast-codegen-x64.cc b/deps/v8/src/x64/fast-codegen-x64.cc
index 53ee35758d..b938119cd3 100644
--- a/deps/v8/src/x64/fast-codegen-x64.cc
+++ b/deps/v8/src/x64/fast-codegen-x64.cc
@@ -118,9 +118,11 @@ void FastCodeGenerator::Generate(FunctionLiteral* fun) {
void FastCodeGenerator::Move(Location destination, Slot* source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
__ push(Operand(rbp, SlotOffset(source)));
break;
}
@@ -129,9 +131,11 @@ void FastCodeGenerator::Move(Location destination, Slot* source) {
void FastCodeGenerator::Move(Location destination, Literal* expr) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
break;
- case Location::TEMP:
+ case Location::kValue:
__ Push(expr->handle());
break;
}
@@ -140,9 +144,10 @@ void FastCodeGenerator::Move(Location destination, Literal* expr) {
void FastCodeGenerator::Move(Slot* destination, Location source) {
switch (source.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized: // Fall through.
+ case Location::kEffect:
UNREACHABLE();
- case Location::TEMP:
+ case Location::kValue:
__ pop(Operand(rbp, SlotOffset(destination)));
break;
}
@@ -151,10 +156,12 @@ void FastCodeGenerator::Move(Slot* destination, Location source) {
void FastCodeGenerator::DropAndMove(Location destination, Register source) {
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
__ addq(rsp, Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::kValue:
__ movq(Operand(rsp, 0), source);
break;
}
@@ -246,6 +253,33 @@ void FastCodeGenerator::VisitVariableProxy(VariableProxy* expr) {
}
+void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ Comment cmnt(masm_, "[ RegExp Literal");
+ Label done;
+ // Registers will be used as follows:
+ // rdi = JS function.
+ // rbx = literals array.
+ // rax = regexp literal.
+ __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
+ __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
+ int literal_offset =
+ FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
+ __ movq(rax, FieldOperand(rbx, literal_offset));
+ __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
+ __ j(not_equal, &done);
+ // Create regexp literal using runtime function
+ // Result will be in rax.
+ __ push(rbx);
+ __ Push(Smi::FromInt(expr->literal_index()));
+ __ Push(expr->pattern());
+ __ Push(expr->flags());
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
+ // Label done:
+ __ bind(&done);
+ Move(expr->location(), rax);
+}
+
+
void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Comment cmnt(masm_, "[ ObjectLiteral");
Label boilerplate_exists;
@@ -295,7 +329,7 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::COMPUTED:
if (key->handle()->IsSymbol()) {
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ pop(rax);
__ Move(rcx, key->handle());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
@@ -307,9 +341,9 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::PROTOTYPE:
__ push(rax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kSetProperty, 3);
__ movq(rax, Operand(rsp, 0)); // Restore result into rax.
break;
@@ -317,12 +351,12 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
__ push(rax);
Visit(key);
- ASSERT(key->location().is_temporary());
+ ASSERT(key->location().is_value());
__ Push(property->kind() == ObjectLiteral::Property::SETTER ?
Smi::FromInt(1) :
Smi::FromInt(0));
Visit(value);
- ASSERT(value->location().is_temporary());
+ ASSERT(value->location().is_value());
__ CallRuntime(Runtime::kDefineAccessor, 4);
__ movq(rax, Operand(rsp, 0)); // Restore result into rax.
break;
@@ -330,43 +364,18 @@ void FastCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
}
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
if (result_saved) __ addq(rsp, Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::kValue:
if (!result_saved) __ push(rax);
break;
}
}
-void FastCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
- Comment cmnt(masm_, "[ RegExp Literal");
- Label done;
- // Registers will be used as follows:
- // rdi = JS function.
- // rbx = literals array.
- // rax = regexp literal.
- __ movq(rdi, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
- __ movq(rbx, FieldOperand(rdi, JSFunction::kLiteralsOffset));
- int literal_offset =
- FixedArray::kHeaderSize + expr->literal_index() * kPointerSize;
- __ movq(rax, FieldOperand(rbx, literal_offset));
- __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
- __ j(not_equal, &done);
- // Create regexp literal using runtime function
- // Result will be in rax.
- __ push(rbx);
- __ Push(Smi::FromInt(expr->literal_index()));
- __ Push(expr->pattern());
- __ Push(expr->flags());
- __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
- // Label done:
- __ bind(&done);
- Move(expr->location(), rax);
-}
-
-
void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
Label make_clone;
@@ -415,7 +424,7 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
result_saved = true;
}
Visit(subexpr);
- ASSERT(subexpr->location().is_temporary());
+ ASSERT(subexpr->location().is_value());
// Store the subexpression value in the array's elements.
__ pop(rax); // Subexpression value.
@@ -429,10 +438,12 @@ void FastCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
if (result_saved) __ addq(rsp, Immediate(kPointerSize));
break;
- case Location::TEMP:
+ case Location::kValue:
if (!result_saved) __ push(rax);
break;
}
@@ -459,7 +470,7 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
if (rhs->AsLiteral() != NULL) {
__ Move(rax, rhs->AsLiteral()->handle());
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
__ pop(rax);
}
@@ -480,14 +491,16 @@ void FastCodeGenerator::VisitAssignment(Assignment* expr) {
__ movq(Operand(rbp, SlotOffset(var->slot())), kScratchRegister);
Move(expr->location(), kScratchRegister);
} else {
- ASSERT(rhs->location().is_temporary());
+ ASSERT(rhs->location().is_value());
Visit(rhs);
switch (expr->location().type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
// Case 'var = temp'. Discard right-hand-side temporary.
Move(var->slot(), rhs->location());
break;
- case Location::TEMP:
+ case Location::kValue:
// Case 'temp1 <- (var = temp0)'. Preserve right-hand-side
// temporary on the stack.
__ movq(kScratchRegister, Operand(rsp, 0));
@@ -532,10 +545,12 @@ void FastCodeGenerator::VisitProperty(Property* expr) {
__ addq(rsp, Immediate(kPointerSize));
}
switch (expr->location().type()) {
- case Location::TEMP:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kValue:
__ movq(Operand(rsp, 0), rax);
break;
- case Location::NOWHERE:
+ case Location::kEffect:
__ addq(rsp, Immediate(kPointerSize));
break;
}
@@ -555,7 +570,7 @@ void FastCodeGenerator::VisitCall(Call* expr) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
// Record source position for debugger
SetSourcePosition(expr->position());
@@ -577,8 +592,8 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
// arguments.
// Push function on the stack.
Visit(node->expression());
- ASSERT(node->expression()->location().is_temporary());
- // If location is temporary, already on the stack,
+ ASSERT(node->expression()->location().is_value());
+ // If location is value, already on the stack,
// Push global object (receiver).
__ push(CodeGenerator::GlobalObject());
@@ -588,8 +603,8 @@ void FastCodeGenerator::VisitCallNew(CallNew* node) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
- // If location is temporary, it is already on the stack,
+ ASSERT(args->at(i)->location().is_value());
+ // If location is value, it is already on the stack,
// so nothing to do here.
}
@@ -621,7 +636,7 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
int arg_count = args->length();
for (int i = 0; i < arg_count; i++) {
Visit(args->at(i));
- ASSERT(args->at(i)->location().is_temporary());
+ ASSERT(args->at(i)->location().is_value());
}
__ CallRuntime(function, arg_count);
@@ -630,13 +645,66 @@ void FastCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
- // Compile a short-circuited boolean or operation in a non-test
- // context.
- ASSERT(expr->op() == Token::OR);
+ switch (expr->op()) {
+ case Token::COMMA:
+ ASSERT(expr->left()->location().is_effect());
+ ASSERT_EQ(expr->right()->location().type(), expr->location().type());
+ Visit(expr->left());
+ Visit(expr->right());
+ break;
+
+ case Token::OR:
+ case Token::AND:
+ EmitLogicalOperation(expr);
+ break;
+
+ case Token::ADD:
+ case Token::SUB:
+ case Token::DIV:
+ case Token::MOD:
+ case Token::MUL:
+ case Token::BIT_OR:
+ case Token::BIT_AND:
+ case Token::BIT_XOR:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::SAR: {
+ ASSERT(expr->left()->location().is_value());
+ ASSERT(expr->right()->location().is_value());
+
+ Visit(expr->left());
+ Visit(expr->right());
+ GenericBinaryOpStub stub(expr->op(),
+ NO_OVERWRITE,
+ NO_GENERIC_BINARY_FLAGS);
+ __ CallStub(&stub);
+ Move(expr->location(), rax);
+
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) {
+ // Compile a short-circuited boolean operation in a non-test context.
+
// Compile (e0 || e1) as if it were
// (let (temp = e0) temp ? temp : e1).
+ // Compile (e0 && e1) as if it were
+ // (let (temp = e0) !temp ? temp : e1).
Label eval_right, done;
+ Label *left_true, *left_false; // Where to branch to if lhs has that value.
+ if (expr->op() == Token::OR) {
+ left_true = &done;
+ left_false = &eval_right;
+ } else {
+ left_true = &eval_right;
+ left_false = &done;
+ }
Location destination = expr->location();
Expression* left = expr->left();
Expression* right = expr->right();
@@ -649,17 +717,19 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
// need it as the value of the whole expression.
if (left->AsLiteral() != NULL) {
__ Move(rax, left->AsLiteral()->handle());
- if (destination.is_temporary()) __ push(rax);
+ if (destination.is_value()) __ push(rax);
} else {
Visit(left);
- ASSERT(left->location().is_temporary());
+ ASSERT(left->location().is_value());
switch (destination.type()) {
- case Location::NOWHERE:
+ case Location::kUninitialized:
+ UNREACHABLE();
+ case Location::kEffect:
// Pop the left-hand value into rax because we will not need it as the
// final result.
__ pop(rax);
break;
- case Location::TEMP:
+ case Location::kValue:
// Copy the left-hand value into rax because we may need it as the
// final result.
__ movq(rax, Operand(rsp, 0));
@@ -667,41 +737,41 @@ void FastCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
}
}
// The left-hand value is in rax. It is also on the stack iff the
- // destination location is temporary.
+ // destination location is value.
// Perform fast checks assumed by the stub.
// The undefined value is false.
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
- __ j(equal, &eval_right);
+ __ j(equal, left_false);
__ CompareRoot(rax, Heap::kTrueValueRootIndex); // True is true.
- __ j(equal, &done);
+ __ j(equal, left_true);
__ CompareRoot(rax, Heap::kFalseValueRootIndex); // False is false.
- __ j(equal, &eval_right);
+ __ j(equal, left_false);
ASSERT(kSmiTag == 0);
__ SmiCompare(rax, Smi::FromInt(0)); // The smi zero is false.
- __ j(equal, &eval_right);
+ __ j(equal, left_false);
Condition is_smi = masm_->CheckSmi(rax); // All other smis are true.
- __ j(is_smi, &done);
+ __ j(is_smi, left_true);
// Call the stub for all other cases.
__ push(rax);
ToBooleanStub stub;
__ CallStub(&stub);
__ testq(rax, rax); // The stub returns nonzero for true.
- __ j(not_zero, &done);
+ if (expr->op() == Token::OR) {
+ __ j(not_zero, &done);
+ } else {
+ __ j(zero, &done);
+ }
__ bind(&eval_right);
// Discard the left-hand value if present on the stack.
- if (destination.is_temporary()) {
+ if (destination.is_value()) {
__ addq(rsp, Immediate(kPointerSize));
}
// Save or discard the right-hand value as needed.
- if (right->AsLiteral() != NULL) {
- Move(destination, right->AsLiteral());
- } else {
- Visit(right);
- Move(destination, right->location());
- }
+ Visit(right);
+ ASSERT_EQ(destination.type(), right->location().type());
__ bind(&done);
}
diff --git a/deps/v8/src/x64/frames-x64.cc b/deps/v8/src/x64/frames-x64.cc
index 6a0527cf6d..fe224ad998 100644
--- a/deps/v8/src/x64/frames-x64.cc
+++ b/deps/v8/src/x64/frames-x64.cc
@@ -57,7 +57,11 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
state->sp = sp;
state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
// Determine frame type.
- return EXIT;
+ if (Memory::Address_at(fp + ExitFrameConstants::kDebugMarkOffset) != 0) {
+ return EXIT_DEBUG;
+ } else {
+ return EXIT;
+ }
}
int JavaScriptFrame::GetProvidedParametersCount() const {
@@ -65,10 +69,10 @@ int JavaScriptFrame::GetProvidedParametersCount() const {
}
-void ExitFrame::Iterate(ObjectVisitor* v) const {
- v->VisitPointer(&code_slot());
- // The arguments are traversed as part of the expression stack of
- // the calling frame.
+void ExitFrame::Iterate(ObjectVisitor* a) const {
+ // Exit frames on X64 do not contain any pointers. The arguments
+ // are traversed as part of the expression stack of the calling
+ // frame.
}
byte* InternalFrame::GetCallerStackPointer() const {
diff --git a/deps/v8/src/x64/frames-x64.h b/deps/v8/src/x64/frames-x64.h
index a92b248d88..eefaa0aeb5 100644
--- a/deps/v8/src/x64/frames-x64.h
+++ b/deps/v8/src/x64/frames-x64.h
@@ -63,7 +63,7 @@ class EntryFrameConstants : public AllStatic {
class ExitFrameConstants : public AllStatic {
public:
- static const int kCodeOffset = -2 * kPointerSize;
+ static const int kDebugMarkOffset = -2 * kPointerSize;
static const int kSPOffset = -1 * kPointerSize;
static const int kCallerFPOffset = +0 * kPointerSize;
diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc
index 6bf6e6a712..b2f69bb7a9 100644
--- a/deps/v8/src/x64/macro-assembler-x64.cc
+++ b/deps/v8/src/x64/macro-assembler-x64.cc
@@ -1787,7 +1787,9 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
}
-void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
+void MacroAssembler::EnterExitFrame(StackFrame::Type type, int result_size) {
+ ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
+
// Setup the frame structure on the stack.
// All constants are relative to the frame pointer of the exit frame.
ASSERT(ExitFrameConstants::kCallerSPDisplacement == +2 * kPointerSize);
@@ -1799,12 +1801,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
// Reserve room for entry stack pointer and push the debug marker.
ASSERT(ExitFrameConstants::kSPOffset == -1 * kPointerSize);
push(Immediate(0)); // saved entry sp, patched before call
- if (mode == ExitFrame::MODE_DEBUG) {
- push(Immediate(0));
- } else {
- movq(kScratchRegister, CodeObject(), RelocInfo::EMBEDDED_OBJECT);
- push(kScratchRegister);
- }
+ push(Immediate(type == StackFrame::EXIT_DEBUG ? 1 : 0));
// Save the frame pointer and the context in top.
ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address);
@@ -1824,7 +1821,7 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
#ifdef ENABLE_DEBUGGER_SUPPORT
// Save the state of all registers to the stack from the memory
// location. This is needed to allow nested break points.
- if (mode == ExitFrame::MODE_DEBUG) {
+ if (type == StackFrame::EXIT_DEBUG) {
// TODO(1243899): This should be symmetric to
// CopyRegistersFromStackToMemory() but it isn't! esp is assumed
// correct here, but computed for the other call. Very error
@@ -1863,17 +1860,17 @@ void MacroAssembler::EnterExitFrame(ExitFrame::Mode mode, int result_size) {
}
-void MacroAssembler::LeaveExitFrame(ExitFrame::Mode mode, int result_size) {
+void MacroAssembler::LeaveExitFrame(StackFrame::Type type, int result_size) {
// Registers:
// r15 : argv
#ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points.
- if (mode == ExitFrame::MODE_DEBUG) {
+ if (type == StackFrame::EXIT_DEBUG) {
// It's okay to clobber register rbx below because we don't need
// the function pointer after this.
const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
- int kOffset = ExitFrameConstants::kCodeOffset - kCallerSavedSize;
+ int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
lea(rbx, Operand(rbp, kOffset));
CopyRegistersFromStackToMemory(rbx, rcx, kJSCallerSaved);
}
diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h
index 11cdfc3c4c..4c2f35bd9c 100644
--- a/deps/v8/src/x64/macro-assembler-x64.h
+++ b/deps/v8/src/x64/macro-assembler-x64.h
@@ -106,16 +106,16 @@ class MacroAssembler: public Assembler {
void EnterConstructFrame() { EnterFrame(StackFrame::CONSTRUCT); }
void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
- // Enter specific kind of exit frame; either in normal or
- // debug mode. Expects the number of arguments in register rax and
+ // Enter specific kind of exit frame; either EXIT or
+ // EXIT_DEBUG. Expects the number of arguments in register rax and
// sets up the number of arguments in register rdi and the pointer
// to the first argument in register rsi.
- void EnterExitFrame(ExitFrame::Mode mode, int result_size = 1);
+ void EnterExitFrame(StackFrame::Type type, int result_size = 1);
// Leave the current exit frame. Expects/provides the return value in
// register rax:rdx (untouched) and the pointer to the first
// argument in register rsi.
- void LeaveExitFrame(ExitFrame::Mode mode, int result_size = 1);
+ void LeaveExitFrame(StackFrame::Type type, int result_size = 1);
// ---------------------------------------------------------------------------
diff --git a/deps/v8/test/cctest/SConscript b/deps/v8/test/cctest/SConscript
index 9deefa5542..f041041c11 100644
--- a/deps/v8/test/cctest/SConscript
+++ b/deps/v8/test/cctest/SConscript
@@ -34,7 +34,6 @@ Import('context object_files')
SOURCES = {
'all': [
- 'test-accessors.cc',
'test-alloc.cc',
'test-api.cc',
'test-ast.cc',
diff --git a/deps/v8/test/cctest/cctest.cc b/deps/v8/test/cctest/cctest.cc
index f638ed480f..82a33e6da5 100644
--- a/deps/v8/test/cctest/cctest.cc
+++ b/deps/v8/test/cctest/cctest.cc
@@ -121,6 +121,3 @@ int main(int argc, char* argv[]) {
v8::V8::Dispose();
return 0;
}
-
-RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
-int RegisterThreadedTest::count_ = 0;
diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h
index 404b692b27..a95645e010 100644
--- a/deps/v8/test/cctest/cctest.h
+++ b/deps/v8/test/cctest/cctest.h
@@ -28,8 +28,6 @@
#ifndef CCTEST_H_
#define CCTEST_H_
-#include "v8.h"
-
#ifndef TEST
#define TEST(Name) \
static void Test##Name(); \
@@ -74,138 +72,4 @@ class CcTest {
CcTest* prev_;
};
-// Switches between all the Api tests using the threading support.
-// In order to get a surprising but repeatable pattern of thread
-// switching it has extra semaphores to control the order in which
-// the tests alternate, not relying solely on the big V8 lock.
-//
-// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
-// callbacks. This will have no effect when we are not running the
-// thread fuzzing test. In the thread fuzzing test it will
-// pseudorandomly select a successor thread and switch execution
-// to that thread, suspending the current test.
-class ApiTestFuzzer: public v8::internal::Thread {
- public:
- void CallTest();
- explicit ApiTestFuzzer(int num)
- : test_number_(num),
- gate_(v8::internal::OS::CreateSemaphore(0)),
- active_(true) {
- }
- ~ApiTestFuzzer() { delete gate_; }
-
- // The ApiTestFuzzer is also a Thread, so it has a Run method.
- virtual void Run();
-
- enum PartOfTest { FIRST_PART, SECOND_PART };
-
- static void Setup(PartOfTest part);
- static void RunAllTests();
- static void TearDown();
- // This method switches threads if we are running the Threading test.
- // Otherwise it does nothing.
- static void Fuzz();
- private:
- static bool fuzzing_;
- static int tests_being_run_;
- static int current_;
- static int active_tests_;
- static bool NextThread();
- int test_number_;
- v8::internal::Semaphore* gate_;
- bool active_;
- void ContextSwitch();
- static int GetNextTestNumber();
- static v8::internal::Semaphore* all_tests_done_;
-};
-
-
-#define THREADED_TEST(Name) \
- static void Test##Name(); \
- RegisterThreadedTest register_##Name(Test##Name, #Name); \
- /* */ TEST(Name)
-
-
-class RegisterThreadedTest {
- public:
- explicit RegisterThreadedTest(CcTest::TestFunction* callback,
- const char* name)
- : fuzzer_(NULL), callback_(callback), name_(name) {
- prev_ = first_;
- first_ = this;
- count_++;
- }
- static int count() { return count_; }
- static RegisterThreadedTest* nth(int i) {
- CHECK(i < count());
- RegisterThreadedTest* current = first_;
- while (i > 0) {
- i--;
- current = current->prev_;
- }
- return current;
- }
- CcTest::TestFunction* callback() { return callback_; }
- ApiTestFuzzer* fuzzer_;
- const char* name() { return name_; }
-
- private:
- static RegisterThreadedTest* first_;
- static int count_;
- CcTest::TestFunction* callback_;
- RegisterThreadedTest* prev_;
- const char* name_;
-};
-
-
-// A LocalContext holds a reference to a v8::Context.
-class LocalContext {
- public:
- LocalContext(v8::ExtensionConfiguration* extensions = 0,
- v8::Handle<v8::ObjectTemplate> global_template =
- v8::Handle<v8::ObjectTemplate>(),
- v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>())
- : context_(v8::Context::New(extensions, global_template, global_object)) {
- context_->Enter();
- }
-
- virtual ~LocalContext() {
- context_->Exit();
- context_.Dispose();
- }
-
- v8::Context* operator->() { return *context_; }
- v8::Context* operator*() { return *context_; }
- bool IsReady() { return !context_.IsEmpty(); }
-
- v8::Local<v8::Context> local() {
- return v8::Local<v8::Context>::New(context_);
- }
-
- private:
- v8::Persistent<v8::Context> context_;
-};
-
-
-static inline v8::Local<v8::Value> v8_num(double x) {
- return v8::Number::New(x);
-}
-
-
-static inline v8::Local<v8::String> v8_str(const char* x) {
- return v8::String::New(x);
-}
-
-
-static inline v8::Local<v8::Script> v8_compile(const char* x) {
- return v8::Script::Compile(v8_str(x));
-}
-
-
-// Helper function that compiles and runs the source.
-static inline v8::Local<v8::Value> CompileRun(const char* source) {
- return v8::Script::Compile(v8::String::New(source))->Run();
-}
-
-
#endif // ifndef CCTEST_H_
diff --git a/deps/v8/test/cctest/test-accessors.cc b/deps/v8/test/cctest/test-accessors.cc
deleted file mode 100644
index b56238ad69..0000000000
--- a/deps/v8/test/cctest/test-accessors.cc
+++ /dev/null
@@ -1,424 +0,0 @@
-// Copyright 2009 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.
-
-#include <stdlib.h>
-
-#include "v8.h"
-
-#include "api.h"
-#include "cctest.h"
-#include "frames-inl.h"
-#include "string-stream.h"
-
-using ::v8::ObjectTemplate;
-using ::v8::Value;
-using ::v8::Context;
-using ::v8::Local;
-using ::v8::String;
-using ::v8::Script;
-using ::v8::Function;
-using ::v8::AccessorInfo;
-using ::v8::Extension;
-
-namespace i = ::v8::internal;
-
-static v8::Handle<Value> handle_property(Local<String> name,
- const AccessorInfo&) {
- ApiTestFuzzer::Fuzz();
- return v8_num(900);
-}
-
-
-THREADED_TEST(PropertyHandler) {
- v8::HandleScope scope;
- Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
- fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
- LocalContext env;
- Local<Function> fun = fun_templ->GetFunction();
- env->Global()->Set(v8_str("Fun"), fun);
- Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
- CHECK_EQ(900, getter->Run()->Int32Value());
- Local<Script> setter = v8_compile("obj.foo = 901;");
- CHECK_EQ(901, setter->Run()->Int32Value());
-}
-
-
-static v8::Handle<Value> GetIntValue(Local<String> property,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- int* value =
- static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
- return v8_num(*value);
-}
-
-
-static void SetIntValue(Local<String> property,
- Local<Value> value,
- const AccessorInfo& info) {
- int* field =
- static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
- *field = value->Int32Value();
-}
-
-int foo, bar, baz;
-
-THREADED_TEST(GlobalVariableAccess) {
- foo = 0;
- bar = -4;
- baz = 10;
- v8::HandleScope scope;
- v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
- templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
- GetIntValue,
- SetIntValue,
- v8::External::New(&foo));
- templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
- GetIntValue,
- SetIntValue,
- v8::External::New(&bar));
- templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
- GetIntValue,
- SetIntValue,
- v8::External::New(&baz));
- LocalContext env(0, templ->InstanceTemplate());
- v8_compile("foo = (++bar) + baz")->Run();
- CHECK_EQ(bar, -3);
- CHECK_EQ(foo, 7);
-}
-
-
-static int x_register = 0;
-static v8::Handle<v8::Object> x_receiver;
-static v8::Handle<v8::Object> x_holder;
-
-
-static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- CHECK_EQ(x_receiver, info.This());
- CHECK_EQ(x_holder, info.Holder());
- return v8_num(x_register);
-}
-
-
-static void XSetter(Local<String> name,
- Local<Value> value,
- const AccessorInfo& info) {
- CHECK_EQ(x_holder, info.This());
- CHECK_EQ(x_holder, info.Holder());
- x_register = value->Int32Value();
-}
-
-
-THREADED_TEST(AccessorIC) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("x"), XGetter, XSetter);
- LocalContext context;
- x_holder = obj->NewInstance();
- context->Global()->Set(v8_str("holder"), x_holder);
- x_receiver = v8::Object::New();
- context->Global()->Set(v8_str("obj"), x_receiver);
- v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
- "obj.__proto__ = holder;"
- "var result = [];"
- "for (var i = 0; i < 10; i++) {"
- " holder.x = i;"
- " result.push(obj.x);"
- "}"
- "result"));
- CHECK_EQ(10, array->Length());
- for (int i = 0; i < 10; i++) {
- v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
- CHECK_EQ(v8::Integer::New(i), entry);
- }
-}
-
-
-static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
- Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- return v8::True();
-}
-
-
-THREADED_TEST(AccessorProhibitsOverwriting) {
- v8::HandleScope scope;
- LocalContext context;
- Local<ObjectTemplate> templ = ObjectTemplate::New();
- templ->SetAccessor(v8_str("x"),
- AccessorProhibitsOverwritingGetter,
- 0,
- v8::Handle<Value>(),
- v8::PROHIBITS_OVERWRITING,
- v8::ReadOnly);
- Local<v8::Object> instance = templ->NewInstance();
- context->Global()->Set(v8_str("obj"), instance);
- Local<Value> value = CompileRun(
- "obj.__defineGetter__('x', function() { return false; });"
- "obj.x");
- CHECK(value->BooleanValue());
- value = CompileRun(
- "var setter_called = false;"
- "obj.__defineSetter__('x', function() { setter_called = true; });"
- "obj.x = 42;"
- "setter_called");
- CHECK(!value->BooleanValue());
- value = CompileRun(
- "obj2 = {};"
- "obj2.__proto__ = obj;"
- "obj2.__defineGetter__('x', function() { return false; });"
- "obj2.x");
- CHECK(value->BooleanValue());
- value = CompileRun(
- "var setter_called = false;"
- "obj2 = {};"
- "obj2.__proto__ = obj;"
- "obj2.__defineSetter__('x', function() { setter_called = true; });"
- "obj2.x = 42;"
- "setter_called");
- CHECK(!value->BooleanValue());
-}
-
-
-template <int C>
-static v8::Handle<Value> HandleAllocatingGetter(Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- for (int i = 0; i < C; i++)
- v8::String::New("foo");
- return v8::String::New("foo");
-}
-
-
-THREADED_TEST(HandleScopePop) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("one"), HandleAllocatingGetter<1>);
- obj->SetAccessor(v8_str("many"), HandleAllocatingGetter<1024>);
- LocalContext context;
- v8::Handle<v8::Object> inst = obj->NewInstance();
- context->Global()->Set(v8::String::New("obj"), inst);
- int count_before = i::HandleScope::NumberOfHandles();
- {
- v8::HandleScope scope;
- CompileRun(
- "for (var i = 0; i < 1000; i++) {"
- " obj.one;"
- " obj.many;"
- "}");
- }
- int count_after = i::HandleScope::NumberOfHandles();
- CHECK_EQ(count_before, count_after);
-}
-
-static v8::Handle<Value> CheckAccessorArgsCorrect(Local<String> name,
- const AccessorInfo& info) {
- CHECK(info.This() == info.Holder());
- CHECK(info.Data()->Equals(v8::String::New("data")));
- ApiTestFuzzer::Fuzz();
- CHECK(info.This() == info.Holder());
- CHECK(info.Data()->Equals(v8::String::New("data")));
- i::Heap::CollectAllGarbage(true);
- CHECK(info.This() == info.Holder());
- CHECK(info.Data()->Equals(v8::String::New("data")));
- return v8::Integer::New(17);
-}
-
-THREADED_TEST(DirectCall) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("xxx"),
- CheckAccessorArgsCorrect,
- NULL,
- v8::String::New("data"));
- LocalContext context;
- v8::Handle<v8::Object> inst = obj->NewInstance();
- context->Global()->Set(v8::String::New("obj"), inst);
- Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
- for (int i = 0; i < 10; i++) {
- Local<Value> result = scr->Run();
- CHECK(!result.IsEmpty());
- CHECK_EQ(17, result->Int32Value());
- }
-}
-
-static v8::Handle<Value> EmptyGetter(Local<String> name,
- const AccessorInfo& info) {
- CheckAccessorArgsCorrect(name, info);
- ApiTestFuzzer::Fuzz();
- CheckAccessorArgsCorrect(name, info);
- return v8::Handle<v8::Value>();
-}
-
-THREADED_TEST(EmptyResult) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
- LocalContext context;
- v8::Handle<v8::Object> inst = obj->NewInstance();
- context->Global()->Set(v8::String::New("obj"), inst);
- Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
- for (int i = 0; i < 10; i++) {
- Local<Value> result = scr->Run();
- CHECK(result == v8::Undefined());
- }
-}
-
-
-THREADED_TEST(NoReuseRegress) {
- // Check that the IC generated for the one test doesn't get reused
- // for the other.
- v8::HandleScope scope;
- {
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("xxx"), EmptyGetter, NULL, v8::String::New("data"));
- LocalContext context;
- v8::Handle<v8::Object> inst = obj->NewInstance();
- context->Global()->Set(v8::String::New("obj"), inst);
- Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
- for (int i = 0; i < 2; i++) {
- Local<Value> result = scr->Run();
- CHECK(result == v8::Undefined());
- }
- }
- {
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("xxx"),
- CheckAccessorArgsCorrect,
- NULL,
- v8::String::New("data"));
- LocalContext context;
- v8::Handle<v8::Object> inst = obj->NewInstance();
- context->Global()->Set(v8::String::New("obj"), inst);
- Local<Script> scr = v8::Script::Compile(v8::String::New("obj.xxx"));
- for (int i = 0; i < 10; i++) {
- Local<Value> result = scr->Run();
- CHECK(!result.IsEmpty());
- CHECK_EQ(17, result->Int32Value());
- }
- }
-}
-
-static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- return v8::ThrowException(v8_str("g"));
-}
-
-
-static void ThrowingSetAccessor(Local<String> name,
- Local<Value> value,
- const AccessorInfo& info) {
- v8::ThrowException(value);
-}
-
-
-THREADED_TEST(Regress1054726) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("x"),
- ThrowingGetAccessor,
- ThrowingSetAccessor,
- Local<Value>());
-
- LocalContext env;
- env->Global()->Set(v8_str("obj"), obj->NewInstance());
-
- // Use the throwing property setter/getter in a loop to force
- // the accessor ICs to be initialized.
- v8::Handle<Value> result;
- result = Script::Compile(v8_str(
- "var result = '';"
- "for (var i = 0; i < 5; i++) {"
- " try { obj.x; } catch (e) { result += e; }"
- "}; result"))->Run();
- CHECK_EQ(v8_str("ggggg"), result);
-
- result = Script::Compile(String::New(
- "var result = '';"
- "for (var i = 0; i < 5; i++) {"
- " try { obj.x = i; } catch (e) { result += e; }"
- "}; result"))->Run();
- CHECK_EQ(v8_str("01234"), result);
-}
-
-
-static v8::Handle<Value> AllocGetter(Local<String> name,
- const AccessorInfo& info) {
- ApiTestFuzzer::Fuzz();
- return v8::Array::New(1000);
-}
-
-
-THREADED_TEST(Gc) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- obj->SetAccessor(v8_str("xxx"), AllocGetter);
- LocalContext env;
- env->Global()->Set(v8_str("obj"), obj->NewInstance());
- Script::Compile(String::New(
- "var last = [];"
- "for (var i = 0; i < 2048; i++) {"
- " var result = obj.xxx;"
- " result[0] = last;"
- " last = result;"
- "}"))->Run();
-}
-
-
-static v8::Handle<Value> StackCheck(Local<String> name,
- const AccessorInfo& info) {
- i::StackFrameIterator iter;
- for (int i = 0; !iter.done(); i++) {
- i::StackFrame* frame = iter.frame();
- CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
- CHECK(frame->code()->IsCode());
- i::Address pc = frame->pc();
- i::Code* code = frame->code();
- CHECK(code->contains(pc));
- iter.Advance();
- }
- return v8::Undefined();
-}
-
-
-THREADED_TEST(StackIteration) {
- v8::HandleScope scope;
- v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
- i::StringStream::ClearMentionedObjectCache();
- obj->SetAccessor(v8_str("xxx"), StackCheck);
- LocalContext env;
- env->Global()->Set(v8_str("obj"), obj->NewInstance());
- Script::Compile(String::New(
- "function foo() {"
- " return obj.xxx;"
- "}"
- "for (var i = 0; i < 100; i++) {"
- " foo();"
- "}"))->Run();
-}
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc
index 83038ae1a7..1d4b2c34c3 100644
--- a/deps/v8/test/cctest/test-api.cc
+++ b/deps/v8/test/cctest/test-api.cc
@@ -38,8 +38,6 @@
#include "utils.h"
#include "cctest.h"
-static const bool kLogThreading = false;
-
static bool IsNaN(double x) {
#ifdef WIN32
return _isnan(x);
@@ -60,6 +58,131 @@ using ::v8::Extension;
namespace i = ::v8::internal;
+static Local<Value> v8_num(double x) {
+ return v8::Number::New(x);
+}
+
+
+static Local<String> v8_str(const char* x) {
+ return String::New(x);
+}
+
+
+static Local<Script> v8_compile(const char* x) {
+ return Script::Compile(v8_str(x));
+}
+
+
+// A LocalContext holds a reference to a v8::Context.
+class LocalContext {
+ public:
+ LocalContext(v8::ExtensionConfiguration* extensions = 0,
+ v8::Handle<ObjectTemplate> global_template =
+ v8::Handle<ObjectTemplate>(),
+ v8::Handle<Value> global_object = v8::Handle<Value>())
+ : context_(Context::New(extensions, global_template, global_object)) {
+ context_->Enter();
+ }
+
+ virtual ~LocalContext() {
+ context_->Exit();
+ context_.Dispose();
+ }
+
+ Context* operator->() { return *context_; }
+ Context* operator*() { return *context_; }
+ Local<Context> local() { return Local<Context>::New(context_); }
+ bool IsReady() { return !context_.IsEmpty(); }
+
+ private:
+ v8::Persistent<Context> context_;
+};
+
+
+// Switches between all the Api tests using the threading support.
+// In order to get a surprising but repeatable pattern of thread
+// switching it has extra semaphores to control the order in which
+// the tests alternate, not relying solely on the big V8 lock.
+//
+// A test is augmented with calls to ApiTestFuzzer::Fuzz() in its
+// callbacks. This will have no effect when we are not running the
+// thread fuzzing test. In the thread fuzzing test it will
+// pseudorandomly select a successor thread and switch execution
+// to that thread, suspending the current test.
+class ApiTestFuzzer: public v8::internal::Thread {
+ public:
+ void CallTest();
+ explicit ApiTestFuzzer(int num)
+ : test_number_(num),
+ gate_(v8::internal::OS::CreateSemaphore(0)),
+ active_(true) {
+ }
+ ~ApiTestFuzzer() { delete gate_; }
+
+ // The ApiTestFuzzer is also a Thread, so it has a Run method.
+ virtual void Run();
+
+ enum PartOfTest { FIRST_PART, SECOND_PART };
+
+ static void Setup(PartOfTest part);
+ static void RunAllTests();
+ static void TearDown();
+ // This method switches threads if we are running the Threading test.
+ // Otherwise it does nothing.
+ static void Fuzz();
+ private:
+ static bool fuzzing_;
+ static int tests_being_run_;
+ static int current_;
+ static int active_tests_;
+ static bool NextThread();
+ int test_number_;
+ v8::internal::Semaphore* gate_;
+ bool active_;
+ void ContextSwitch();
+ static int GetNextTestNumber();
+ static v8::internal::Semaphore* all_tests_done_;
+};
+
+
+#define THREADED_TEST(Name) \
+ static void Test##Name(); \
+ RegisterThreadedTest register_##Name(Test##Name); \
+ /* */ TEST(Name)
+
+
+class RegisterThreadedTest {
+ public:
+ explicit RegisterThreadedTest(CcTest::TestFunction* callback)
+ : fuzzer_(NULL), callback_(callback) {
+ prev_ = first_;
+ first_ = this;
+ count_++;
+ }
+ static int count() { return count_; }
+ static RegisterThreadedTest* nth(int i) {
+ CHECK(i < count());
+ RegisterThreadedTest* current = first_;
+ while (i > 0) {
+ i--;
+ current = current->prev_;
+ }
+ return current;
+ }
+ CcTest::TestFunction* callback() { return callback_; }
+ ApiTestFuzzer* fuzzer_;
+
+ private:
+ static RegisterThreadedTest* first_;
+ static int count_;
+ CcTest::TestFunction* callback_;
+ RegisterThreadedTest* prev_;
+};
+
+
+RegisterThreadedTest *RegisterThreadedTest::first_ = NULL;
+int RegisterThreadedTest::count_ = 0;
+
static int signature_callback_count;
static v8::Handle<Value> IncrementingSignatureCallback(
@@ -108,6 +231,11 @@ THREADED_TEST(Handles) {
}
+// Helper function that compiles and runs the source.
+static Local<Value> CompileRun(const char* source) {
+ return Script::Compile(String::New(source))->Run();
+}
+
THREADED_TEST(ReceiverSignature) {
v8::HandleScope scope;
LocalContext env;
@@ -592,6 +720,27 @@ THREADED_TEST(FindInstanceInPrototypeChain) {
}
+static v8::Handle<Value> handle_property(Local<String> name,
+ const AccessorInfo&) {
+ ApiTestFuzzer::Fuzz();
+ return v8_num(900);
+}
+
+
+THREADED_TEST(PropertyHandler) {
+ v8::HandleScope scope;
+ Local<v8::FunctionTemplate> fun_templ = v8::FunctionTemplate::New();
+ fun_templ->InstanceTemplate()->SetAccessor(v8_str("foo"), handle_property);
+ LocalContext env;
+ Local<Function> fun = fun_templ->GetFunction();
+ env->Global()->Set(v8_str("Fun"), fun);
+ Local<Script> getter = v8_compile("var obj = new Fun(); obj.foo;");
+ CHECK_EQ(900, getter->Run()->Int32Value());
+ Local<Script> setter = v8_compile("obj.foo = 901;");
+ CHECK_EQ(901, setter->Run()->Int32Value());
+}
+
+
THREADED_TEST(TinyInteger) {
v8::HandleScope scope;
LocalContext env;
@@ -758,6 +907,49 @@ THREADED_TEST(GlobalPrototype) {
}
+static v8::Handle<Value> GetIntValue(Local<String> property,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ int* value =
+ static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+ return v8_num(*value);
+}
+
+static void SetIntValue(Local<String> property,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ int* field =
+ static_cast<int*>(v8::Handle<v8::External>::Cast(info.Data())->Value());
+ *field = value->Int32Value();
+}
+
+int foo, bar, baz;
+
+THREADED_TEST(GlobalVariableAccess) {
+ foo = 0;
+ bar = -4;
+ baz = 10;
+ v8::HandleScope scope;
+ v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
+ templ->InstanceTemplate()->SetAccessor(v8_str("foo"),
+ GetIntValue,
+ SetIntValue,
+ v8::External::New(&foo));
+ templ->InstanceTemplate()->SetAccessor(v8_str("bar"),
+ GetIntValue,
+ SetIntValue,
+ v8::External::New(&bar));
+ templ->InstanceTemplate()->SetAccessor(v8_str("baz"),
+ GetIntValue,
+ SetIntValue,
+ v8::External::New(&baz));
+ LocalContext env(0, templ->InstanceTemplate());
+ v8_compile("foo = (++bar) + baz")->Run();
+ CHECK_EQ(bar, -3);
+ CHECK_EQ(foo, 7);
+}
+
+
THREADED_TEST(ObjectTemplate) {
v8::HandleScope scope;
Local<ObjectTemplate> templ1 = ObjectTemplate::New();
@@ -1173,6 +1365,50 @@ THREADED_TEST(CallbackExceptionRegression) {
}
+static v8::Handle<Value> ThrowingGetAccessor(Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ return v8::ThrowException(v8_str("g"));
+}
+
+
+static void ThrowingSetAccessor(Local<String> name,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ v8::ThrowException(value);
+}
+
+
+THREADED_TEST(Regress1054726) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("x"),
+ ThrowingGetAccessor,
+ ThrowingSetAccessor,
+ Local<Value>());
+
+ LocalContext env;
+ env->Global()->Set(v8_str("obj"), obj->NewInstance());
+
+ // Use the throwing property setter/getter in a loop to force
+ // the accessor ICs to be initialized.
+ v8::Handle<Value> result;
+ result = Script::Compile(v8_str(
+ "var result = '';"
+ "for (var i = 0; i < 5; i++) {"
+ " try { obj.x; } catch (e) { result += e; }"
+ "}; result"))->Run();
+ CHECK_EQ(v8_str("ggggg"), result);
+
+ result = Script::Compile(String::New(
+ "var result = '';"
+ "for (var i = 0; i < 5; i++) {"
+ " try { obj.x = i; } catch (e) { result += e; }"
+ "}; result"))->Run();
+ CHECK_EQ(v8_str("01234"), result);
+}
+
+
THREADED_TEST(FunctionPrototype) {
v8::HandleScope scope;
Local<v8::FunctionTemplate> Foo = v8::FunctionTemplate::New();
@@ -2948,6 +3184,53 @@ THREADED_TEST(Arguments) {
}
+static int x_register = 0;
+static v8::Handle<v8::Object> x_receiver;
+static v8::Handle<v8::Object> x_holder;
+
+
+static v8::Handle<Value> XGetter(Local<String> name, const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ CHECK_EQ(x_receiver, info.This());
+ CHECK_EQ(x_holder, info.Holder());
+ return v8_num(x_register);
+}
+
+
+static void XSetter(Local<String> name,
+ Local<Value> value,
+ const AccessorInfo& info) {
+ CHECK_EQ(x_holder, info.This());
+ CHECK_EQ(x_holder, info.Holder());
+ x_register = value->Int32Value();
+}
+
+
+THREADED_TEST(AccessorIC) {
+ v8::HandleScope scope;
+ v8::Handle<v8::ObjectTemplate> obj = ObjectTemplate::New();
+ obj->SetAccessor(v8_str("x"), XGetter, XSetter);
+ LocalContext context;
+ x_holder = obj->NewInstance();
+ context->Global()->Set(v8_str("holder"), x_holder);
+ x_receiver = v8::Object::New();
+ context->Global()->Set(v8_str("obj"), x_receiver);
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(CompileRun(
+ "obj.__proto__ = holder;"
+ "var result = [];"
+ "for (var i = 0; i < 10; i++) {"
+ " holder.x = i;"
+ " result.push(obj.x);"
+ "}"
+ "result"));
+ CHECK_EQ(10, array->Length());
+ for (int i = 0; i < 10; i++) {
+ v8::Handle<Value> entry = array->Get(v8::Integer::New(i));
+ CHECK_EQ(v8::Integer::New(i), entry);
+ }
+}
+
+
static v8::Handle<Value> NoBlockGetterX(Local<String> name,
const AccessorInfo&) {
return v8::Handle<Value>();
@@ -5811,17 +6094,13 @@ void ApiTestFuzzer::Fuzz() {
// not start immediately.
bool ApiTestFuzzer::NextThread() {
int test_position = GetNextTestNumber();
- const char* test_name = RegisterThreadedTest::nth(current_)->name();
+ int test_number = RegisterThreadedTest::nth(current_)->fuzzer_->test_number_;
if (test_position == current_) {
- if (kLogThreading)
- printf("Stay with %s\n", test_name);
+ printf("Stay with %d\n", test_number);
return false;
}
- if (kLogThreading) {
- printf("Switch from %s to %s\n",
- test_name,
- RegisterThreadedTest::nth(test_position)->name());
- }
+ printf("Switch from %d to %d\n",
+ current_ < 0 ? 0 : test_number, test_position < 0 ? 0 : test_number);
current_ = test_position;
RegisterThreadedTest::nth(current_)->fuzzer_->gate_->Signal();
return true;
@@ -5930,11 +6209,9 @@ TEST(Threading2) {
void ApiTestFuzzer::CallTest() {
- if (kLogThreading)
- printf("Start test %d\n", test_number_);
+ printf("Start test %d\n", test_number_);
CallTestNumber(test_number_);
- if (kLogThreading)
- printf("End test %d\n", test_number_);
+ printf("End test %d\n", test_number_);
}
@@ -6422,6 +6699,53 @@ THREADED_TEST(PropertyEnumeration) {
}
+static v8::Handle<Value> AccessorProhibitsOverwritingGetter(
+ Local<String> name,
+ const AccessorInfo& info) {
+ ApiTestFuzzer::Fuzz();
+ return v8::True();
+}
+
+
+THREADED_TEST(AccessorProhibitsOverwriting) {
+ v8::HandleScope scope;
+ LocalContext context;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetAccessor(v8_str("x"),
+ AccessorProhibitsOverwritingGetter,
+ 0,
+ v8::Handle<Value>(),
+ v8::PROHIBITS_OVERWRITING,
+ v8::ReadOnly);
+ Local<v8::Object> instance = templ->NewInstance();
+ context->Global()->Set(v8_str("obj"), instance);
+ Local<Value> value = CompileRun(
+ "obj.__defineGetter__('x', function() { return false; });"
+ "obj.x");
+ CHECK(value->BooleanValue());
+ value = CompileRun(
+ "var setter_called = false;"
+ "obj.__defineSetter__('x', function() { setter_called = true; });"
+ "obj.x = 42;"
+ "setter_called");
+ CHECK(!value->BooleanValue());
+ value = CompileRun(
+ "obj2 = {};"
+ "obj2.__proto__ = obj;"
+ "obj2.__defineGetter__('x', function() { return false; });"
+ "obj2.x");
+ CHECK(value->BooleanValue());
+ value = CompileRun(
+ "var setter_called = false;"
+ "obj2 = {};"
+ "obj2.__proto__ = obj;"
+ "obj2.__defineSetter__('x', function() { setter_called = true; });"
+ "obj2.x = 42;"
+ "setter_called");
+ CHECK(!value->BooleanValue());
+}
+
+
static bool NamedSetAccessBlocker(Local<v8::Object> obj,
Local<Value> name,
v8::AccessType type,
diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc
index 656a456faa..4ffcee3dbf 100644
--- a/deps/v8/test/cctest/test-debug.cc
+++ b/deps/v8/test/cctest/test-debug.cc
@@ -178,6 +178,12 @@ static v8::Local<v8::Function> CompileFunction(const char* source,
}
+// Helper function that compiles and runs the source.
+static v8::Local<v8::Value> CompileRun(const char* source) {
+ return v8::Script::Compile(v8::String::New(source))->Run();
+}
+
+
// Is there any debug info for the function?
static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
diff --git a/deps/v8/test/cctest/test-log-stack-tracer.cc b/deps/v8/test/cctest/test-log-stack-tracer.cc
index 68cbc26191..39f90647e3 100644
--- a/deps/v8/test/cctest/test-log-stack-tracer.cc
+++ b/deps/v8/test/cctest/test-log-stack-tracer.cc
@@ -163,6 +163,11 @@ v8::Handle<v8::Value> TraceExtension::JSEntrySP(const v8::Arguments& args) {
}
+static void CompileRun(const char* source) {
+ Script::Compile(String::New(source))->Run();
+}
+
+
v8::Handle<v8::Value> TraceExtension::JSEntrySPLevel2(
const v8::Arguments& args) {
v8::HandleScope scope;
diff --git a/deps/v8/test/mjsunit/fuzz-natives.js b/deps/v8/test/mjsunit/fuzz-natives.js
index f495c72787..cdf58a559a 100644
--- a/deps/v8/test/mjsunit/fuzz-natives.js
+++ b/deps/v8/test/mjsunit/fuzz-natives.js
@@ -129,9 +129,7 @@ var knownProblems = {
"Log": true,
"DeclareGlobals": true,
- "CollectStackTrace": true,
- "PromoteScheduledException": true,
- "DeleteHandleScopeExtensions": true
+ "CollectStackTrace": true
};
var currentlyUncallable = {