Version 3.1.3.
Fixed a bug triggered by functions with huge numbers of declared arguments.
Fixed zap value aliasing a real object - debug mode only. Issue 866.
Fixed issue where Array.prototype.__proto__ had been set to null. Issue 1121.
Fixed stability bugs in Crankshaft for x86.
Review URL: http://codereview.chromium.org/6460038
git-svn-id: http://v8.googlecode.com/svn/trunk@6711 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/AUTHORS b/AUTHORS
index 1b756ca..92b69cb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,6 +9,7 @@
Hewlett-Packard Development Company, LP
Alexander Botero-Lowry <alexbl@FreeBSD.org>
+Alexander Karpinsky <homm86@gmail.com>
Alexandre Vassalotti <avassalotti@gmail.com>
Andreas Anyuru <andreas.anyuru@gmail.com>
Bert Belder <bertbelder@gmail.com>
diff --git a/ChangeLog b/ChangeLog
index d48ded8..235ba23 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2011-02-09: Version 3.1.3
+
+ Fixed a bug triggered by functions with huge numbers of declared
+ arguments.
+
+ Fixed zap value aliasing a real object - debug mode only. Issue 866.
+
+ Fixed issue where Array.prototype.__proto__ had been set to null.
+ Issue 1121.
+
+ Fixed stability bugs in Crankshaft for x86.
+
+
2011-02-07: Version 3.1.2
Added better security checks when accessing properties via
diff --git a/src/api.cc b/src/api.cc
index c162440..80a53bf 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -115,7 +115,9 @@
static void DefaultFatalErrorHandler(const char* location,
const char* message) {
- ENTER_V8;
+#ifdef ENABLE_VMSTATE_TRACKING
+ i::VMState __state__(i::OTHER);
+#endif
API_Fatal(location, message);
}
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 1284223..87c4968 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -2192,15 +2192,10 @@
DeleteFrame();
#ifdef DEBUG
- // Check that the size of the code used for returning matches what is
- // expected by the debugger. If the sp_delts above cannot be encoded in
- // the add instruction the add will generate two instructions.
- int return_sequence_length =
- masm_->InstructionsGeneratedSince(&check_exit_codesize);
- CHECK(return_sequence_length ==
- Assembler::kJSReturnSequenceInstructions ||
- return_sequence_length ==
- Assembler::kJSReturnSequenceInstructions + 1);
+ // Check that the size of the code used for returning is large enough
+ // for the debugger's requirements.
+ ASSERT(Assembler::kJSReturnSequenceInstructions <=
+ masm_->InstructionsGeneratedSince(&check_exit_codesize));
#endif
}
}
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index ff446c5..37e5504 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -268,15 +268,10 @@
}
#ifdef DEBUG
- // Check that the size of the code used for returning matches what is
- // expected by the debugger. If the sp_delts above cannot be encoded in the
- // add instruction the add will generate two instructions.
- int return_sequence_length =
- masm_->InstructionsGeneratedSince(&check_exit_codesize);
- CHECK(return_sequence_length ==
- Assembler::kJSReturnSequenceInstructions ||
- return_sequence_length ==
- Assembler::kJSReturnSequenceInstructions + 1);
+ // Check that the size of the code used for returning is large enough
+ // for the debugger's requirements.
+ ASSERT(Assembler::kJSReturnSequenceInstructions <=
+ masm_->InstructionsGeneratedSince(&check_exit_codesize));
#endif
}
}
@@ -681,18 +676,24 @@
} else if (prop != NULL) {
if (function != NULL || mode == Variable::CONST) {
// We are declaring a function or constant that rewrites to a
- // property. Use (keyed) IC to set the initial value.
- VisitForStackValue(prop->obj());
- if (function != NULL) {
- VisitForStackValue(prop->key());
- VisitForAccumulatorValue(function);
- __ pop(r1); // Key.
- } else {
- VisitForAccumulatorValue(prop->key());
- __ mov(r1, result_register()); // Key.
- __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
+ // property. Use (keyed) IC to set the initial value. We
+ // cannot visit the rewrite because it's shared and we risk
+ // recording duplicate AST IDs for bailouts from optimized code.
+ ASSERT(prop->obj()->AsVariableProxy() != NULL);
+ { AccumulatorValueContext for_object(this);
+ EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
}
- __ pop(r2); // Receiver.
+ if (function != NULL) {
+ __ push(r0);
+ VisitForAccumulatorValue(function);
+ __ pop(r2);
+ } else {
+ __ mov(r2, r0);
+ __ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
+ }
+ ASSERT(prop->key()->AsLiteral() != NULL &&
+ prop->key()->AsLiteral()->handle()->IsSmi());
+ __ mov(r1, Operand(prop->key()->AsLiteral()->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
EmitCallIC(ic, RelocInfo::CODE_TARGET);
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index f672d49..3e2cc16 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1077,6 +1077,8 @@
} else if (v->IsTypeofIs()) {
HTypeofIs* typeof_is = HTypeofIs::cast(v);
return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
+ } else if (v->IsIsConstructCall()) {
+ return new LIsConstructCallAndBranch(TempRegister());
} else {
if (v->IsConstant()) {
if (HConstant::cast(v)->handle()->IsTrue()) {
@@ -1304,10 +1306,10 @@
// the generated code, which requires registers r0
// and r1 to be used. We should remove that
// when we provide a native implementation.
- LOperand* value = UseFixed(instr->left(), r0);
+ LOperand* dividend = UseFixed(instr->left(), r0);
LOperand* divisor = UseFixed(instr->right(), r1);
return AssignEnvironment(AssignPointerMap(
- DefineFixed(new LDivI(value, divisor), r0)));
+ DefineFixed(new LDivI(dividend, divisor), r0)));
} else {
return DoArithmeticT(Token::DIV, instr);
}
@@ -1642,13 +1644,11 @@
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
Representation r = instr->representation();
if (r.IsInteger32()) {
- int32_t value = instr->Integer32Value();
- return DefineAsRegister(new LConstantI(value));
+ return DefineAsRegister(new LConstantI);
} else if (r.IsDouble()) {
- double value = instr->DoubleValue();
- return DefineAsRegister(new LConstantD(value));
+ return DefineAsRegister(new LConstantD);
} else if (r.IsTagged()) {
- return DefineAsRegister(new LConstantT(instr->handle()));
+ return DefineAsRegister(new LConstantT);
} else {
UNREACHABLE();
return NULL;
@@ -1890,6 +1890,12 @@
return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
}
+
+LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
+ return DefineAsRegister(new LIsConstructCall());
+}
+
+
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
HEnvironment* env = current_block_->last_environment();
ASSERT(env != NULL);
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index a076c80..7591f94 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -41,7 +41,6 @@
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
V(ControlInstruction) \
- V(Constant) \
V(Call) \
V(StoreKeyed) \
V(StoreNamed) \
@@ -153,6 +152,8 @@
V(Typeof) \
V(TypeofIs) \
V(TypeofIsAndBranch) \
+ V(IsConstructCall) \
+ V(IsConstructCallAndBranch) \
V(UnaryMathOperation) \
V(UnknownOSRValue) \
V(ValueOf)
@@ -903,44 +904,30 @@
};
-class LConstant: public LTemplateInstruction<1, 0, 0> {
- DECLARE_INSTRUCTION(Constant)
-};
-
-
-class LConstantI: public LConstant {
+class LConstantI: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantI(int32_t value) : value_(value) { }
- int32_t value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- int32_t value_;
+ int32_t value() const { return hydrogen()->Integer32Value(); }
};
-class LConstantD: public LConstant {
+class LConstantD: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantD(double value) : value_(value) { }
- double value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- double value_;
+ double value() const { return hydrogen()->DoubleValue(); }
};
-class LConstantT: public LConstant {
+class LConstantT: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantT(Handle<Object> value) : value_(value) { }
- Handle<Object> value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- Handle<Object> value_;
+ Handle<Object> value() const { return hydrogen()->handle(); }
};
@@ -1716,6 +1703,24 @@
};
+class LIsConstructCall: public LTemplateInstruction<1, 0, 0> {
+ public:
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is-construct-call")
+ DECLARE_HYDROGEN_ACCESSOR(IsConstructCall)
+};
+
+
+class LIsConstructCallAndBranch: public LControlInstruction<0, 1> {
+ public:
+ explicit LIsConstructCallAndBranch(LOperand* temp) {
+ temps_[0] = temp;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
+ "is-construct-call-and-branch")
+};
+
+
class LDeleteProperty: public LTemplateInstruction<1, 2, 0> {
public:
LDeleteProperty(LOperand* obj, LOperand* key) {
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 855ed46..4179872 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -647,7 +647,7 @@
return;
}
- if (cc == kNoCondition) {
+ if (cc == al) {
if (FLAG_trap_on_deopt) __ stop("trap_on_deopt");
__ Jump(entry, RelocInfo::RUNTIME_ENTRY);
} else {
@@ -1188,8 +1188,8 @@
__ tst(left, Operand(left));
__ b(ne, &done);
if (instr->InputAt(1)->IsConstantOperand()) {
- if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) < 0) {
- DeoptimizeIf(kNoCondition, instr->environment());
+ if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
+ DeoptimizeIf(al, instr->environment());
}
} else {
// Test the non-zero operand for negative sign.
@@ -3778,6 +3778,55 @@
}
+void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
+ Register result = ToRegister(instr->result());
+ Label true_label;
+ Label false_label;
+ Label done;
+
+ EmitIsConstructCall(result, scratch0());
+ __ b(eq, &true_label);
+
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ b(&done);
+
+
+ __ bind(&true_label);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+
+ __ bind(&done);
+}
+
+
+void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
+ Register temp1 = ToRegister(instr->TempAt(0));
+ int true_block = chunk_->LookupDestination(instr->true_block_id());
+ int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+ EmitIsConstructCall(temp1, scratch0());
+ EmitBranch(true_block, false_block, eq);
+}
+
+
+void LCodeGen::EmitIsConstructCall(Register temp1, Register temp2) {
+ ASSERT(!temp1.is(temp2));
+ // Get the frame pointer for the calling frame.
+ __ ldr(temp1, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+
+ // Skip the arguments adaptor frame if it exists.
+ Label check_frame_marker;
+ __ ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
+ __ cmp(temp2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ b(ne, &check_frame_marker);
+ __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
+
+ // Check the marker in the calling frame.
+ __ bind(&check_frame_marker);
+ __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset));
+ __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
+}
+
+
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
// No code for lazy bailout instruction. Used to capture environment after a
// call for populating the safepoint data with deoptimization data.
@@ -3785,7 +3834,7 @@
void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
- DeoptimizeIf(kNoCondition, instr->environment());
+ DeoptimizeIf(al, instr->environment());
}
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index 3f7fe45..7bc6689 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -264,6 +264,10 @@
Label* is_not_object,
Label* is_object);
+ // Emits optimized code for %_IsConstructCall().
+ // Caller should branch on equal condition.
+ void EmitIsConstructCall(Register temp1, Register temp2);
+
LChunk* const chunk_;
MacroAssembler* const masm_;
CompilationInfo* const info_;
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index c11d664..7347ebf 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -1150,7 +1150,8 @@
// Calculate new top and bail out if new space is exhausted. Use result
// to calculate the new top.
- add(scratch2, result, Operand(obj_size_reg));
+ add(scratch2, result, Operand(obj_size_reg), SetCC);
+ b(cs, gc_required);
cmp(scratch2, Operand(ip));
b(hi, gc_required);
str(scratch2, MemOperand(topaddr));
@@ -1229,10 +1230,11 @@
// to calculate the new top. Object size may be in words so a shift is
// required to get the number of bytes.
if ((flags & SIZE_IN_WORDS) != 0) {
- add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2));
+ add(scratch2, result, Operand(object_size, LSL, kPointerSizeLog2), SetCC);
} else {
- add(scratch2, result, Operand(object_size));
+ add(scratch2, result, Operand(object_size), SetCC);
}
+ b(cs, gc_required);
cmp(scratch2, Operand(ip));
b(hi, gc_required);
diff --git a/src/builtins.cc b/src/builtins.cc
index d604226..0373cdc 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -368,7 +368,9 @@
array_proto = JSObject::cast(array_proto->GetPrototype());
ASSERT(array_proto->elements() == Heap::empty_fixed_array());
// Object.prototype
- array_proto = JSObject::cast(array_proto->GetPrototype());
+ Object* proto = array_proto->GetPrototype();
+ if (proto == Heap::null_value()) return false;
+ array_proto = JSObject::cast(proto);
if (array_proto != global_context->initial_object_prototype()) return false;
if (array_proto->elements() != Heap::empty_fixed_array()) return false;
ASSERT(array_proto->GetPrototype()->IsNull());
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 4ed3fec..252fb92 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -913,7 +913,7 @@
Breakable nested_statement(this, stmt);
SetStatementPosition(stmt);
- PrepareForBailoutForId(stmt->EntryId(), TOS_REG);
+ PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
VisitStatements(stmt->statements());
__ bind(nested_statement.break_target());
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
diff --git a/src/handles.cc b/src/handles.cc
index 274c34d..795eda0 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -808,6 +808,7 @@
ClearExceptionFlag flag) {
// Compile the source information to a code object.
ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
+ ASSERT(!Top::has_pending_exception());
bool result = Compiler::CompileLazy(info);
ASSERT(result != Top::has_pending_exception());
if (!result && flag == CLEAR_EXCEPTION) Top::clear_pending_exception();
diff --git a/src/heap.cc b/src/heap.cc
index 0e3a2b8..f88ebda 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -4128,7 +4128,7 @@
#ifdef DEBUG
void Heap::ZapFromSpace() {
- ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsHeapObject());
+ ASSERT(reinterpret_cast<Object*>(kFromSpaceZapValue)->IsFailure());
for (Address a = new_space_.FromSpaceLow();
a < new_space_.FromSpaceHigh();
a += kPointerSize) {
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 0ff41ba..6d251d1 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -900,17 +900,6 @@
}
-bool HPhi::HasReceiverOperand() {
- for (int i = 0; i < OperandCount(); i++) {
- if (OperandAt(i)->IsParameter() &&
- HParameter::cast(OperandAt(i))->index() == 0) {
- return true;
- }
- }
- return false;
-}
-
-
HValue* HPhi::GetRedundantReplacement() const {
HValue* candidate = NULL;
int count = OperandCount();
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index f1093a0..05ff68c 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -113,6 +113,7 @@
V(IsNull) \
V(IsObject) \
V(IsSmi) \
+ V(IsConstructCall) \
V(HasInstanceType) \
V(HasCachedArrayIndex) \
V(JSArrayLength) \
@@ -1701,7 +1702,7 @@
HValue* GetRedundantReplacement() const;
void AddInput(HValue* value);
- bool HasReceiverOperand();
+ bool IsReceiver() { return merged_index_ == 0; }
int merged_index() const { return merged_index_; }
@@ -2179,6 +2180,22 @@
};
+class HIsConstructCall: public HInstruction {
+ public:
+ HIsConstructCall() {
+ set_representation(Representation::Tagged());
+ SetFlag(kUseGVN);
+ }
+
+ virtual bool EmitAtUses() const { return uses()->length() <= 1; }
+
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is_construct_call")
+
+ protected:
+ virtual bool DataEquals(HValue* other) const { return true; }
+};
+
+
class HHasInstanceType: public HUnaryPredicate {
public:
HHasInstanceType(HValue* value, InstanceType type)
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 4044f7f..be45d3e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -870,13 +870,11 @@
}
uses_to_replace.Rewind(0);
block->RemovePhi(phi);
- } else if (phi->HasNoUses() &&
- !phi->HasReceiverOperand() &&
- FLAG_eliminate_dead_phis) {
- // We can't eliminate phis that have the receiver as an operand
- // because in case of throwing an error we need the correct
- // receiver value in the environment to construct a corrent
- // stack trace.
+ } else if (FLAG_eliminate_dead_phis && phi->HasNoUses() &&
+ !phi->IsReceiver()) {
+ // We can't eliminate phis in the receiver position in the environment
+ // because in case of throwing an error we need this value to
+ // construct a stack trace.
block->RemovePhi(phi);
block->RecordDeletedPhi(phi->merged_index());
}
@@ -2952,6 +2950,9 @@
if (is_store && lookup->IsReadOnly()) {
BAILOUT("read-only global variable");
}
+ if (lookup->holder() != *global) {
+ BAILOUT("global property on prototype of global object");
+ }
}
@@ -5185,9 +5186,10 @@
}
- // Support for construct call checks.
+// Support for construct call checks.
void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) {
- BAILOUT("inlined runtime function: IsConstructCall");
+ ASSERT(argument_count == 0);
+ ast_context()->ReturnInstruction(new HIsConstructCall, ast_id);
}
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index 552d7b5..e4d09f2 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -2559,6 +2559,19 @@
}
+void Assembler::pinsrd(XMMRegister dst, const Operand& src, int8_t offset) {
+ ASSERT(CpuFeatures::IsEnabled(SSE4_1));
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ EMIT(0x66);
+ EMIT(0x0F);
+ EMIT(0x3A);
+ EMIT(0x22);
+ emit_sse_operand(dst, src);
+ EMIT(offset);
+}
+
+
void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
Register ireg = { reg.code() };
emit_operand(ireg, adr);
diff --git a/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index 20446b0..2e84d6f 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -928,6 +928,7 @@
void psrlq(XMMRegister dst, XMMRegister src);
void pshufd(XMMRegister dst, XMMRegister src, int8_t shuffle);
void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
+ void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
// Parallel XMM operations.
void movntdqa(XMMRegister src, const Operand& dst);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index cfee970..7d70ac3 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -4723,6 +4723,23 @@
__ test(ecx, Immediate(kFailureTagMask));
__ j(zero, &failure_returned, not_taken);
+ ExternalReference pending_exception_address(Top::k_pending_exception_address);
+
+ // Check that there is no pending exception, otherwise we
+ // should have returned some failure value.
+ if (FLAG_debug_code) {
+ __ push(edx);
+ __ mov(edx, Operand::StaticVariable(
+ ExternalReference::the_hole_value_location()));
+ NearLabel okay;
+ __ cmp(edx, Operand::StaticVariable(pending_exception_address));
+ // Cannot use check here as it attempts to generate call into runtime.
+ __ j(equal, &okay);
+ __ int3();
+ __ bind(&okay);
+ __ pop(edx);
+ }
+
// Exit the JavaScript to C++ exit frame.
__ LeaveExitFrame(save_doubles_);
__ ret(0);
@@ -4741,7 +4758,6 @@
__ j(equal, throw_out_of_memory_exception);
// Retrieve the pending exception and clear the variable.
- ExternalReference pending_exception_address(Top::k_pending_exception_address);
__ mov(eax, Operand::StaticVariable(pending_exception_address));
__ mov(edx,
Operand::StaticVariable(ExternalReference::the_hole_value_location()));
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index 52de32b..0d8b03d 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -3771,14 +3771,15 @@
// Leave the frame and return popping the arguments and the
// receiver.
frame_->Exit();
- masm_->ret((scope()->num_parameters() + 1) * kPointerSize);
+ int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
+ __ Ret(arguments_bytes, ecx);
DeleteFrame();
#ifdef ENABLE_DEBUGGER_SUPPORT
- // Check that the size of the code used for returning matches what is
- // expected by the debugger.
- ASSERT_EQ(Assembler::kJSReturnSequenceLength,
- masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
+ // Check that the size of the code used for returning is large enough
+ // for the debugger's requirements.
+ ASSERT(Assembler::kJSReturnSequenceLength <=
+ masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
#endif
}
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 4028a93..e0cbe35 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -1115,10 +1115,20 @@
get_modrm(*data, &mod, ®op, &rm);
int8_t imm8 = static_cast<int8_t>(data[1]);
AppendToBuffer("pextrd %s,%s,%d",
- NameOfXMMRegister(regop),
+ NameOfCPURegister(regop),
NameOfXMMRegister(rm),
static_cast<int>(imm8));
data += 2;
+ } else if (*data == 0x22) {
+ data++;
+ int mod, regop, rm;
+ get_modrm(*data, &mod, ®op, &rm);
+ int8_t imm8 = static_cast<int8_t>(data[1]);
+ AppendToBuffer("pinsrd %s,%s,%d",
+ NameOfXMMRegister(regop),
+ NameOfCPURegister(rm),
+ static_cast<int>(imm8));
+ data += 2;
} else {
UnimplementedInstruction();
}
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 3c094a4..c081efc 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -310,12 +310,14 @@
// patch with the code required by the debugger.
__ mov(esp, ebp);
__ pop(ebp);
- __ ret((scope()->num_parameters() + 1) * kPointerSize);
+
+ int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
+ __ Ret(arguments_bytes, ecx);
#ifdef ENABLE_DEBUGGER_SUPPORT
- // Check that the size of the code used for returning matches what is
- // expected by the debugger.
- ASSERT_EQ(Assembler::kJSReturnSequenceLength,
- masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
+ // Check that the size of the code used for returning is large enough
+ // for the debugger's requirements.
+ ASSERT(Assembler::kJSReturnSequenceLength <=
+ masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
#endif
}
}
@@ -717,18 +719,25 @@
} else if (prop != NULL) {
if (function != NULL || mode == Variable::CONST) {
// We are declaring a function or constant that rewrites to a
- // property. Use (keyed) IC to set the initial value.
- VisitForStackValue(prop->obj());
- if (function != NULL) {
- VisitForStackValue(prop->key());
- VisitForAccumulatorValue(function);
- __ pop(ecx);
- } else {
- VisitForAccumulatorValue(prop->key());
- __ mov(ecx, result_register());
- __ mov(result_register(), Factory::the_hole_value());
+ // property. Use (keyed) IC to set the initial value. We cannot
+ // visit the rewrite because it's shared and we risk recording
+ // duplicate AST IDs for bailouts from optimized code.
+ ASSERT(prop->obj()->AsVariableProxy() != NULL);
+ { AccumulatorValueContext for_object(this);
+ EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
}
- __ pop(edx);
+
+ if (function != NULL) {
+ __ push(eax);
+ VisitForAccumulatorValue(function);
+ __ pop(edx);
+ } else {
+ __ mov(edx, eax);
+ __ mov(eax, Factory::the_hole_value());
+ }
+ ASSERT(prop->key()->AsLiteral() != NULL &&
+ prop->key()->AsLiteral()->handle()->IsSmi());
+ __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
EmitCallIC(ic, RelocInfo::CODE_TARGET);
@@ -3949,8 +3958,7 @@
// Call stub for +1/-1.
__ mov(edx, eax);
__ mov(eax, Immediate(Smi::FromInt(1)));
- TypeRecordingBinaryOpStub stub(expr->binary_op(),
- NO_OVERWRITE);
+ TypeRecordingBinaryOpStub stub(expr->binary_op(), NO_OVERWRITE);
EmitCallIC(stub.GetCode(), &patch_site);
__ bind(&done);
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 9e4bada..b6a6382 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -804,7 +804,7 @@
__ test(left, Operand(left));
__ j(not_zero, &done);
if (right->IsConstantOperand()) {
- if (ToInteger32(LConstantOperand::cast(right)) < 0) {
+ if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
DeoptimizeIf(no_condition, instr->environment());
}
} else {
@@ -945,19 +945,31 @@
if (BitCast<uint64_t, double>(v) == 0) {
__ xorpd(res, res);
} else {
- int32_t v_int32 = static_cast<int32_t>(v);
- if (static_cast<double>(v_int32) == v) {
- __ push_imm32(v_int32);
- __ cvtsi2sd(res, Operand(esp, 0));
- __ add(Operand(esp), Immediate(kPointerSize));
+ Register temp = ToRegister(instr->TempAt(0));
+ uint64_t int_val = BitCast<uint64_t, double>(v);
+ int32_t lower = static_cast<int32_t>(int_val);
+ int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatures::Scope scope(SSE4_1);
+ if (lower != 0) {
+ __ Set(temp, Immediate(lower));
+ __ movd(res, Operand(temp));
+ __ Set(temp, Immediate(upper));
+ __ pinsrd(res, Operand(temp), 1);
+ } else {
+ __ xorpd(res, res);
+ __ Set(temp, Immediate(upper));
+ __ pinsrd(res, Operand(temp), 1);
+ }
} else {
- uint64_t int_val = BitCast<uint64_t, double>(v);
- int32_t lower = static_cast<int32_t>(int_val);
- int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
- __ push_imm32(upper);
- __ push_imm32(lower);
- __ movdbl(res, Operand(esp, 0));
- __ add(Operand(esp), Immediate(2 * kPointerSize));
+ __ Set(temp, Immediate(upper));
+ __ movd(res, Operand(temp));
+ __ psllq(res, 32);
+ if (lower != 0) {
+ __ Set(temp, Immediate(lower));
+ __ movd(xmm0, Operand(temp));
+ __ por(res, xmm0);
+ }
}
}
}
@@ -1881,7 +1893,7 @@
}
__ mov(esp, ebp);
__ pop(ebp);
- __ ret((ParameterCount() + 1) * kPointerSize);
+ __ Ret((ParameterCount() + 1) * kPointerSize, ecx);
}
@@ -2035,7 +2047,10 @@
ASSERT(result.is(elements));
// Load the result.
- __ mov(result, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));
+ __ mov(result, FieldOperand(elements,
+ key,
+ times_pointer_size,
+ FixedArray::kHeaderSize));
// Check for the hole value.
__ cmp(result, Factory::the_hole_value());
@@ -2661,13 +2676,20 @@
ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
__ mov(FieldOperand(elements, offset), value);
} else {
- __ mov(FieldOperand(elements, key, times_4, FixedArray::kHeaderSize),
+ __ mov(FieldOperand(elements,
+ key,
+ times_pointer_size,
+ FixedArray::kHeaderSize),
value);
}
if (instr->hydrogen()->NeedsWriteBarrier()) {
// Compute address of modified element and store it into key register.
- __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize));
+ __ lea(key,
+ FieldOperand(elements,
+ key,
+ times_pointer_size,
+ FixedArray::kHeaderSize));
__ RecordWrite(elements, key, value);
}
}
@@ -3577,6 +3599,53 @@
}
+void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
+ Register result = ToRegister(instr->result());
+ NearLabel true_label;
+ NearLabel false_label;
+ NearLabel done;
+
+ EmitIsConstructCall(result);
+ __ j(equal, &true_label);
+
+ __ mov(result, Factory::false_value());
+ __ jmp(&done);
+
+ __ bind(&true_label);
+ __ mov(result, Factory::true_value());
+
+ __ bind(&done);
+}
+
+
+void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
+ Register temp = ToRegister(instr->TempAt(0));
+ int true_block = chunk_->LookupDestination(instr->true_block_id());
+ int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+ EmitIsConstructCall(temp);
+ EmitBranch(true_block, false_block, equal);
+}
+
+
+void LCodeGen::EmitIsConstructCall(Register temp) {
+ // Get the frame pointer for the calling frame.
+ __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
+
+ // Skip the arguments adaptor frame if it exists.
+ NearLabel check_frame_marker;
+ __ cmp(Operand(temp, StandardFrameConstants::kContextOffset),
+ Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ j(not_equal, &check_frame_marker);
+ __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset));
+
+ // Check the marker in the calling frame.
+ __ bind(&check_frame_marker);
+ __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset),
+ Immediate(Smi::FromInt(StackFrame::CONSTRUCT)));
+}
+
+
void LCodeGen::DoLazyBailout(LLazyBailout* instr) {
// No code for lazy bailout instruction. Used to capture environment after a
// call for populating the safepoint data with deoptimization data.
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index f0379c0..3782208 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -229,6 +229,11 @@
Label* is_not_object,
Label* is_object);
+ // Emits optimized code for %_IsConstructCall().
+ // Caller should branch on equal condition.
+ void EmitIsConstructCall(Register temp);
+
+
LChunk* const chunk_;
MacroAssembler* const masm_;
CompilationInfo* const info_;
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index b31c4eb..793a3f4 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1098,6 +1098,8 @@
} else if (v->IsTypeofIs()) {
HTypeofIs* typeof_is = HTypeofIs::cast(v);
return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
+ } else if (v->IsIsConstructCall()) {
+ return new LIsConstructCallAndBranch(TempRegister());
} else {
if (v->IsConstant()) {
if (HConstant::cast(v)->handle()->IsTrue()) {
@@ -1320,9 +1322,9 @@
// The temporary operand is necessary to ensure that right is not allocated
// into edx.
LOperand* temp = FixedTemp(edx);
- LOperand* value = UseFixed(instr->left(), eax);
+ LOperand* dividend = UseFixed(instr->left(), eax);
LOperand* divisor = UseRegister(instr->right());
- LDivI* result = new LDivI(value, divisor, temp);
+ LDivI* result = new LDivI(dividend, divisor, temp);
return AssignEnvironment(DefineFixed(result, eax));
} else {
ASSERT(instr->representation().IsTagged());
@@ -1672,13 +1674,15 @@
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
Representation r = instr->representation();
if (r.IsInteger32()) {
- int32_t value = instr->Integer32Value();
- return DefineAsRegister(new LConstantI(value));
+ return DefineAsRegister(new LConstantI);
} else if (r.IsDouble()) {
double value = instr->DoubleValue();
- return DefineAsRegister(new LConstantD(value));
+ LOperand* temp = (BitCast<uint64_t, double>(value) != 0)
+ ? TempRegister()
+ : NULL;
+ return DefineAsRegister(new LConstantD(temp));
} else if (r.IsTagged()) {
- return DefineAsRegister(new LConstantT(instr->handle()));
+ return DefineAsRegister(new LConstantT);
} else {
UNREACHABLE();
return NULL;
@@ -1925,6 +1929,12 @@
return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value())));
}
+
+LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
+ return DefineAsRegister(new LIsConstructCall);
+}
+
+
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
HEnvironment* env = current_block_->last_environment();
ASSERT(env != NULL);
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index f643dac..56d031c 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -41,7 +41,6 @@
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
V(ControlInstruction) \
- V(Constant) \
V(Call) \
V(StoreKeyed) \
V(StoreNamed) \
@@ -112,6 +111,8 @@
V(IsObjectAndBranch) \
V(IsSmi) \
V(IsSmiAndBranch) \
+ V(IsConstructCall) \
+ V(IsConstructCallAndBranch) \
V(JSArrayLength) \
V(Label) \
V(LazyBailout) \
@@ -755,6 +756,24 @@
};
+class LIsConstructCall: public LTemplateInstruction<1, 0, 0> {
+ public:
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is-construct-call")
+ DECLARE_HYDROGEN_ACCESSOR(IsConstructCall)
+};
+
+
+class LIsConstructCallAndBranch: public LControlInstruction<0, 1> {
+ public:
+ explicit LIsConstructCallAndBranch(LOperand* temp) {
+ temps_[0] = temp;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
+ "is-construct-call-and-branch")
+};
+
+
class LClassOfTest: public LTemplateInstruction<1, 1, 1> {
public:
LClassOfTest(LOperand* value, LOperand* temp) {
@@ -913,44 +932,34 @@
};
-class LConstant: public LTemplateInstruction<1, 0, 0> {
- DECLARE_INSTRUCTION(Constant)
-};
-
-
-class LConstantI: public LConstant {
+class LConstantI: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantI(int32_t value) : value_(value) { }
- int32_t value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- int32_t value_;
+ int32_t value() const { return hydrogen()->Integer32Value(); }
};
-class LConstantD: public LConstant {
+class LConstantD: public LTemplateInstruction<1, 0, 1> {
public:
- explicit LConstantD(double value) : value_(value) { }
- double value() const { return value_; }
+ explicit LConstantD(LOperand* temp) {
+ temps_[0] = temp;
+ }
DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- double value_;
+ double value() const { return hydrogen()->DoubleValue(); }
};
-class LConstantT: public LConstant {
+class LConstantT: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantT(Handle<Object> value) : value_(value) { }
- Handle<Object> value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- Handle<Object> value_;
+ Handle<Object> value() const { return hydrogen()->handle(); }
};
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index ee4e3d9..9ed0643 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -604,11 +604,11 @@
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
- if (top_reg.is(result)) {
- add(Operand(top_reg), Immediate(object_size));
- } else {
- lea(top_reg, Operand(result, object_size));
+ if (!top_reg.is(result)) {
+ mov(top_reg, result);
}
+ add(Operand(top_reg), Immediate(object_size));
+ j(carry, gc_required, not_taken);
cmp(top_reg, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required, not_taken);
@@ -657,7 +657,12 @@
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
- lea(result_end, Operand(result, element_count, element_size, header_size));
+
+ // We assume that element_count*element_size + header_size does not
+ // overflow.
+ lea(result_end, Operand(element_count, element_size, header_size));
+ add(result_end, Operand(result));
+ j(carry, gc_required);
cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required);
@@ -702,6 +707,7 @@
mov(result_end, object_size);
}
add(result_end, Operand(result));
+ j(carry, gc_required, not_taken);
cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
j(above, gc_required, not_taken);
@@ -1581,6 +1587,20 @@
}
+void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
+ if (is_uint16(bytes_dropped)) {
+ ret(bytes_dropped);
+ } else {
+ pop(scratch);
+ add(Operand(esp), Immediate(bytes_dropped));
+ push(scratch);
+ ret(0);
+ }
+}
+
+
+
+
void MacroAssembler::Drop(int stack_elements) {
if (stack_elements > 0) {
add(Operand(esp), Immediate(stack_elements * kPointerSize));
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index 12a8923..09584f7 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -550,6 +550,10 @@
void Ret();
+ // Return and drop arguments from stack, where the number of arguments
+ // may be bigger than 2^16 - 1. Requires a scratch register.
+ void Ret(int bytes_dropped, Register scratch);
+
// Emit code to discard a non-negative number of pointer-sized elements
// from the stack, clobbering only the esp register.
void Drop(int element_count);
diff --git a/src/messages.cc b/src/messages.cc
index 4323649..990000a 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -69,10 +69,13 @@
Handle<String> stack_trace,
Handle<JSArray> stack_frames) {
Handle<String> type_handle = Factory::LookupAsciiSymbol(type);
- Handle<JSArray> arguments_handle = Factory::NewJSArray(args.length());
+ Handle<FixedArray> arguments_elements =
+ Factory::NewFixedArray(args.length());
for (int i = 0; i < args.length(); i++) {
- SetElement(arguments_handle, i, args[i]);
+ arguments_elements->set(i, *args[i]);
}
+ Handle<JSArray> arguments_handle =
+ Factory::NewJSArrayWithElements(arguments_elements);
int start = 0;
int end = 0;
@@ -87,7 +90,7 @@
? Factory::undefined_value()
: Handle<Object>::cast(stack_trace);
- Handle<Object> stack_frames_handle = stack_frames.is_null()
+ Handle<Object> stack_frames_handle = stack_frames.is_null()
? Factory::undefined_value()
: Handle<Object>::cast(stack_frames);
diff --git a/src/messages.js b/src/messages.js
index d22ac65..1e41b17 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -211,6 +211,7 @@
invalid_preparser_data: ["Invalid preparser data for function ", "%0"],
strict_mode_with: ["Strict mode code may not include a with statement"],
strict_catch_variable: ["Catch variable may not be eval or arguments in strict mode"],
+ too_many_parameters: ["Too many parameters in function definition"],
strict_param_name: ["Parameter name eval or arguments is not allowed in strict mode"],
strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
strict_var_name: ["Variable name may not be eval or arguments in strict mode"],
@@ -316,6 +317,7 @@
return i;
}
}
+
return -1;
}
diff --git a/src/objects.cc b/src/objects.cc
index 775487a..a6e0dcd 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1707,8 +1707,9 @@
}
-bool JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index,
- Object* value) {
+MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(uint32_t index,
+ Object* value,
+ bool* found) {
for (Object* pt = GetPrototype();
pt != Heap::null_value();
pt = pt->GetPrototype()) {
@@ -1718,15 +1719,16 @@
NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
int entry = dictionary->FindEntry(index);
if (entry != NumberDictionary::kNotFound) {
- Object* element = dictionary->ValueAt(entry);
PropertyDetails details = dictionary->DetailsAt(entry);
if (details.type() == CALLBACKS) {
- SetElementWithCallback(element, index, value, JSObject::cast(pt));
- return true;
+ *found = true;
+ return SetElementWithCallback(
+ dictionary->ValueAt(entry), index, value, JSObject::cast(pt));
}
}
}
- return false;
+ *found = false;
+ return Heap::the_hole_value();
}
@@ -2779,6 +2781,13 @@
MaybeObject* JSObject::PreventExtensions() {
+ if (IsJSGlobalProxy()) {
+ Object* proto = GetPrototype();
+ if (proto->IsNull()) return this;
+ ASSERT(proto->IsJSGlobalObject());
+ return JSObject::cast(proto)->PreventExtensions();
+ }
+
// If there are fast elements we normalize.
if (HasFastElements()) {
Object* ok;
@@ -6962,9 +6971,11 @@
uint32_t elms_length = static_cast<uint32_t>(elms->length());
if (check_prototype &&
- (index >= elms_length || elms->get(index)->IsTheHole()) &&
- SetElementWithCallbackSetterInPrototypes(index, value)) {
- return value;
+ (index >= elms_length || elms->get(index)->IsTheHole())) {
+ bool found;
+ MaybeObject* result =
+ SetElementWithCallbackSetterInPrototypes(index, value, &found);
+ if (found) return result;
}
@@ -7096,9 +7107,11 @@
}
} else {
// Index not already used. Look for an accessor in the prototype chain.
- if (check_prototype &&
- SetElementWithCallbackSetterInPrototypes(index, value)) {
- return value;
+ if (check_prototype) {
+ bool found;
+ MaybeObject* result =
+ SetElementWithCallbackSetterInPrototypes(index, value, &found);
+ if (found) return result;
}
// When we set the is_extensible flag to false we always force
// the element into dictionary mode (and force them to stay there).
diff --git a/src/objects.h b/src/objects.h
index bf59830..71ef506 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1579,7 +1579,8 @@
void LookupRealNamedProperty(String* name, LookupResult* result);
void LookupRealNamedPropertyInPrototypes(String* name, LookupResult* result);
void LookupCallbackSetterInPrototypes(String* name, LookupResult* result);
- bool SetElementWithCallbackSetterInPrototypes(uint32_t index, Object* value);
+ MUST_USE_RESULT MaybeObject* SetElementWithCallbackSetterInPrototypes(
+ uint32_t index, Object* value, bool* found);
void LookupCallback(String* name, LookupResult* result);
// Returns the number of properties on this object filtering out properties
diff --git a/src/parser.cc b/src/parser.cc
index 5353a63..e1a99cb 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -764,8 +764,6 @@
RelocInfo::kNoPosition, type, &ok);
// Make sure the results agree.
ASSERT(ok == (result != NULL));
- // The only errors should be stack overflows.
- ASSERT(ok || stack_overflow_);
}
// Make sure the target stack is empty.
@@ -774,8 +772,8 @@
// If there was a stack overflow we have to get rid of AST and it is
// not safe to do before scope has been deleted.
if (result == NULL) {
- Top::StackOverflow();
zone_scope->DeleteOnExit();
+ if (stack_overflow_) Top::StackOverflow();
} else {
Handle<String> inferred_name(info->inferred_name());
result->set_inferred_name(inferred_name);
@@ -3501,6 +3499,12 @@
Variable* parameter = top_scope_->DeclareLocal(param_name, Variable::VAR);
top_scope_->AddParameter(parameter);
num_parameters++;
+ if (num_parameters > kMaxNumFunctionParameters) {
+ ReportMessageAt(scanner().location(), "too_many_parameters",
+ Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ }
done = (peek() == Token::RPAREN);
if (!done) Expect(Token::COMMA, CHECK_OK);
}
@@ -4058,6 +4062,11 @@
uint32_t index;
if (key->AsArrayIndex(&index)) {
SetOwnElement(json_object, index, value);
+ } else if (key->Equals(Heap::Proto_symbol())) {
+ // We can't remove the __proto__ accessor since it's hardcoded
+ // in several places. Instead go along and add the value as
+ // the prototype of the created object if possible.
+ SetPrototype(json_object, value);
} else {
SetLocalPropertyIgnoreAttributes(json_object, key, value, NONE);
}
diff --git a/src/parser.h b/src/parser.h
index aa8d525..dfd909a 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -436,6 +436,11 @@
Vector<Handle<String> > args);
protected:
+ // Limit on number of function parameters is chosen arbitrarily.
+ // Code::Flags uses only the low 17 bits of num-parameters to
+ // construct a hashable id, so if more than 2^17 are allowed, this
+ // should be checked.
+ static const int kMaxNumFunctionParameters = 32766;
FunctionLiteral* ParseLazy(Handle<SharedFunctionInfo> info,
UC16CharacterStream* source,
ZoneScope* zone_scope);
diff --git a/src/runtime.cc b/src/runtime.cc
index 4994378..5fdd6fb 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -884,10 +884,17 @@
return obj->PreventExtensions();
}
+
static MaybeObject* Runtime_IsExtensible(Arguments args) {
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSObject, obj, args[0]);
- return obj->map()->is_extensible() ? Heap::true_value()
+ if (obj->IsJSGlobalProxy()) {
+ Object* proto = obj->GetPrototype();
+ if (proto->IsNull()) return Heap::false_value();
+ ASSERT(proto->IsJSGlobalObject());
+ obj = JSObject::cast(proto);
+ }
+ return obj->map()->is_extensible() ? Heap::true_value()
: Heap::false_value();
}
@@ -1082,7 +1089,11 @@
const char* type = (lookup.IsReadOnly()) ? "const" : "var";
return ThrowRedeclarationError(type, name);
}
- SetProperty(global, name, value, attributes);
+ Handle<Object> result = SetProperty(global, name, value, attributes);
+ if (result.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return Failure::Exception();
+ }
} else {
// If a property with this name does not already exist on the
// global object add the property locally. We take special
@@ -1090,10 +1101,16 @@
// of callbacks in the prototype chain (this rules out using
// SetProperty). Also, we must use the handle-based version to
// avoid GC issues.
- SetLocalPropertyIgnoreAttributes(global, name, value, attributes);
+ Handle<Object> result =
+ SetLocalPropertyIgnoreAttributes(global, name, value, attributes);
+ if (result.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return Failure::Exception();
+ }
}
}
+ ASSERT(!Top::has_pending_exception());
return Heap::undefined_value();
}
@@ -1143,12 +1160,15 @@
} else {
// The holder is an arguments object.
Handle<JSObject> arguments(Handle<JSObject>::cast(holder));
- SetElement(arguments, index, initial_value);
+ Handle<Object> result = SetElement(arguments, index, initial_value);
+ if (result.is_null()) return Failure::Exception();
}
} else {
// Slow case: The property is not in the FixedArray part of the context.
Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
- SetProperty(context_ext, name, initial_value, mode);
+ Handle<Object> result =
+ SetProperty(context_ext, name, initial_value, mode);
+ if (result.is_null()) return Failure::Exception();
}
}
@@ -1175,8 +1195,8 @@
ASSERT(!context_ext->HasLocalProperty(*name));
Handle<Object> value(Heap::undefined_value());
if (*initial_value != NULL) value = initial_value;
- SetProperty(context_ext, name, value, mode);
- ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
+ Handle<Object> result = SetProperty(context_ext, name, value, mode);
+ if (result.is_null()) return Failure::Exception();
}
return Heap::undefined_value();
@@ -3668,14 +3688,20 @@
if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) &&
is_element) {
// Normalize the elements to enable attributes on the property.
- if (!js_object->IsJSGlobalProxy()) {
- NormalizeElements(js_object);
+ if (js_object->IsJSGlobalProxy()) {
+ Handle<Object> proto(js_object->GetPrototype());
+ // If proxy is detached, ignore the assignment. Alternatively,
+ // we could throw an exception.
+ if (proto->IsNull()) return *obj_value;
+ js_object = Handle<JSObject>::cast(proto);
}
+ NormalizeElements(js_object);
Handle<NumberDictionary> dictionary(js_object->element_dictionary());
// Make sure that we never go back to fast case.
dictionary->set_requires_slow_elements();
PropertyDetails details = PropertyDetails(attr, NORMAL);
NumberDictionarySet(dictionary, index, obj_value, details);
+ return *obj_value;
}
LookupResult result;
@@ -3690,9 +3716,12 @@
if (result.IsProperty() &&
(attr != result.GetAttributes() || result.type() == CALLBACKS)) {
// New attributes - normalize to avoid writing to instance descriptor
- if (!js_object->IsJSGlobalProxy()) {
- NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
+ if (js_object->IsJSGlobalProxy()) {
+ // Since the result is a property, the prototype will exist so
+ // we don't have to check for null.
+ js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
}
+ NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
// Use IgnoreAttributes version since a readonly property may be
// overridden and SetProperty does not allow this.
return js_object->SetLocalPropertyIgnoreAttributes(*name,
@@ -6681,28 +6710,50 @@
return *result;
}
+
static MaybeObject* Runtime_NewObjectFromBound(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
+ // First argument is a function to use as a constructor.
CONVERT_ARG_CHECKED(JSFunction, function, 0);
- CONVERT_ARG_CHECKED(JSArray, params, 1);
- RUNTIME_ASSERT(params->HasFastElements());
- FixedArray* fixed = FixedArray::cast(params->elements());
+ // Second argument is either null or an array of bound arguments.
+ FixedArray* bound_args = NULL;
+ int bound_argc = 0;
+ if (!args[1]->IsNull()) {
+ CONVERT_ARG_CHECKED(JSArray, params, 1);
+ RUNTIME_ASSERT(params->HasFastElements());
+ bound_args = FixedArray::cast(params->elements());
+ bound_argc = Smi::cast(params->length())->value();
+ }
- int fixed_length = Smi::cast(params->length())->value();
- SmartPointer<Object**> param_data(NewArray<Object**>(fixed_length));
- for (int i = 0; i < fixed_length; i++) {
- Handle<Object> val = Handle<Object>(fixed->get(i));
+ // Find frame containing arguments passed to the caller.
+ JavaScriptFrameIterator it;
+ JavaScriptFrame* frame = it.frame();
+ ASSERT(!frame->is_optimized());
+ it.AdvanceToArgumentsFrame();
+ frame = it.frame();
+ int argc = frame->GetProvidedParametersCount();
+
+ // Prepend bound arguments to caller's arguments.
+ int total_argc = bound_argc + argc;
+ SmartPointer<Object**> param_data(NewArray<Object**>(total_argc));
+ for (int i = 0; i < bound_argc; i++) {
+ Handle<Object> val = Handle<Object>(bound_args->get(i));
param_data[i] = val.location();
}
+ for (int i = 0; i < argc; i++) {
+ Handle<Object> val = Handle<Object>(frame->GetParameter(i));
+ param_data[bound_argc + i] = val.location();
+ }
bool exception = false;
- Handle<Object> result = Execution::New(
- function, fixed_length, *param_data, &exception);
+ Handle<Object> result =
+ Execution::New(function, total_argc, *param_data, &exception);
if (exception) {
return Failure::Exception();
}
+
ASSERT(!result.is_null());
return *result;
}
@@ -7340,12 +7391,17 @@
if (holder->IsContext()) {
// Ignore if read_only variable.
if ((attributes & READ_ONLY) == 0) {
- Handle<Context>::cast(holder)->set(index, *value);
+ // Context is a fixed array and set cannot fail.
+ Context::cast(*holder)->set(index, *value);
}
} else {
ASSERT((attributes & READ_ONLY) == 0);
- Handle<JSObject>::cast(holder)->SetElement(index, *value)->
- ToObjectUnchecked();
+ Handle<Object> result =
+ SetElement(Handle<JSObject>::cast(holder), index, value);
+ if (result.is_null()) {
+ ASSERT(Top::has_pending_exception());
+ return Failure::Exception();
+ }
}
return *value;
}
@@ -7368,8 +7424,8 @@
// extension object itself.
if ((attributes & READ_ONLY) == 0 ||
(context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
- Handle<Object> set = SetProperty(context_ext, name, value, NONE);
- if (set.is_null()) {
+ Handle<Object> result = SetProperty(context_ext, name, value, NONE);
+ if (result.is_null()) {
// Failure::Exception is converted to a null handle in the
// handle-based methods such as SetProperty. We therefore need
// to convert null handles back to exceptions.
diff --git a/src/scanner.cc b/src/scanner.cc
index cab8c58..d54d9f9 100755
--- a/src/scanner.cc
+++ b/src/scanner.cc
@@ -76,7 +76,8 @@
buffer_end_ = buffer_ + kBufferSize;
buffer_cursor_ = buffer_end_;
}
- ASSERT(pushback_limit_ > buffer_);
+ // Ensure that there is room for at least one pushback.
+ ASSERT(buffer_cursor_ > buffer_);
ASSERT(pos_ > 0);
buffer_[--buffer_cursor_ - buffer_] = character;
if (buffer_cursor_ == buffer_) {
@@ -89,15 +90,17 @@
bool BufferedUC16CharacterStream::ReadBlock() {
+ buffer_cursor_ = buffer_;
if (pushback_limit_ != NULL) {
- buffer_cursor_ = buffer_;
+ // Leave pushback mode.
buffer_end_ = pushback_limit_;
pushback_limit_ = NULL;
- ASSERT(buffer_cursor_ != buffer_end_);
- return true;
+ // If there were any valid characters left at the
+ // start of the buffer, use those.
+ if (buffer_cursor_ < buffer_end_) return true;
+ // Otherwise read a new block.
}
unsigned length = FillBuffer(pos_, kBufferSize);
- buffer_cursor_ = buffer_;
buffer_end_ = buffer_ + length;
return length > 0;
}
diff --git a/src/uri.js b/src/uri.js
index 179fa92..e94b3fe 100644
--- a/src/uri.js
+++ b/src/uri.js
@@ -90,11 +90,13 @@
}
-function URIHexCharsToCharCode(ch1, ch2) {
- if (HexValueOf(ch1) == -1 || HexValueOf(ch2) == -1) {
+function URIHexCharsToCharCode(highChar, lowChar) {
+ var highCode = HexValueOf(highChar);
+ var lowCode = HexValueOf(lowChar);
+ if (highCode == -1 || lowCode == -1) {
throw new $URIError("URI malformed");
}
- return HexStrToCharCode(ch1 + ch2);
+ return (highCode << 4) | lowCode;
}
@@ -196,7 +198,7 @@
var ch = uri.charAt(k);
if (ch == '%') {
if (k + 2 >= uriLength) throw new $URIError("URI malformed");
- var cc = URIHexCharsToCharCode(uri.charAt(++k), uri.charAt(++k));
+ var cc = URIHexCharsToCharCode(uri.charCodeAt(++k), uri.charCodeAt(++k));
if (cc >> 7) {
var n = 0;
while (((cc << ++n) & 0x80) != 0) ;
@@ -206,7 +208,7 @@
if (k + 3 * (n - 1) >= uriLength) throw new $URIError("URI malformed");
for (var i = 1; i < n; i++) {
if (uri.charAt(++k) != '%') throw new $URIError("URI malformed");
- octets[i] = URIHexCharsToCharCode(uri.charAt(++k), uri.charAt(++k));
+ octets[i] = URIHexCharsToCharCode(uri.charCodeAt(++k), uri.charCodeAt(++k));
}
index = URIDecodeOctets(octets, result, index);
} else {
@@ -325,9 +327,7 @@
}
-function HexValueOf(c) {
- var code = c.charCodeAt(0);
-
+function HexValueOf(code) {
// 0-9
if (code >= 48 && code <= 57) return code - 48;
// A-F
@@ -356,18 +356,6 @@
}
-// Converts hex string to char code. Not efficient.
-function HexStrToCharCode(s) {
- var m = 0;
- var r = 0;
- for (var i = s.length - 1; i >= 0; --i) {
- r = r + (HexValueOf(s.charAt(i)) << m);
- m = m + 4;
- }
- return r;
-}
-
-
// Returns true if all digits in string s are valid hex numbers
function IsValidHex(s) {
for (var i = 0; i < s.length; ++i) {
diff --git a/src/v8globals.h b/src/v8globals.h
index 85bd17e..d11bc38 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -69,21 +69,21 @@
// Zap-value: The value used for zapping dead objects.
-// Should be a recognizable hex value tagged as a heap object pointer.
+// Should be a recognizable hex value tagged as a failure.
#ifdef V8_HOST_ARCH_64_BIT
const Address kZapValue =
- reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeed));
+ reinterpret_cast<Address>(V8_UINT64_C(0xdeadbeedbeadbeef));
const Address kHandleZapValue =
- reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddead));
+ reinterpret_cast<Address>(V8_UINT64_C(0x1baddead0baddeaf));
const Address kFromSpaceZapValue =
- reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdad));
+ reinterpret_cast<Address>(V8_UINT64_C(0x1beefdad0beefdaf));
const uint64_t kDebugZapValue = V8_UINT64_C(0xbadbaddbbadbaddb);
-const uint64_t kSlotsZapValue = V8_UINT64_C(0xbeefdeadbeefdeed);
+const uint64_t kSlotsZapValue = V8_UINT64_C(0xbeefdeadbeefdeef);
#else
-const Address kZapValue = reinterpret_cast<Address>(0xdeadbeed);
-const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddead);
-const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdad);
-const uint32_t kSlotsZapValue = 0xbeefdeed;
+const Address kZapValue = reinterpret_cast<Address>(0xdeadbeef);
+const Address kHandleZapValue = reinterpret_cast<Address>(0xbaddeaf);
+const Address kFromSpaceZapValue = reinterpret_cast<Address>(0xbeefdaf);
+const uint32_t kSlotsZapValue = 0xbeefdeef;
const uint32_t kDebugZapValue = 0xbadbaddb;
#endif
diff --git a/src/v8natives.js b/src/v8natives.js
index b0fb5bf..83b00b0 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1153,33 +1153,49 @@
}
// this_arg is not an argument that should be bound.
var argc_bound = (%_ArgumentsLength() || 1) - 1;
- if (argc_bound > 0) {
+ var fn = this;
+ if (argc_bound == 0) {
+ var result = function() {
+ if (%_IsConstructCall()) {
+ // %NewObjectFromBound implicitly uses arguments passed to this
+ // function. We do not pass the arguments object explicitly to avoid
+ // materializing it and guarantee that this function will be optimized.
+ return %NewObjectFromBound(fn, null);
+ }
+
+ return fn.apply(this_arg, arguments);
+ };
+ } else {
var bound_args = new $Array(argc_bound);
for(var i = 0; i < argc_bound; i++) {
bound_args[i] = %_Arguments(i+1);
}
+
+ var result = function() {
+ // If this is a construct call we use a special runtime method
+ // to generate the actual object using the bound function.
+ if (%_IsConstructCall()) {
+ // %NewObjectFromBound implicitly uses arguments passed to this
+ // function. We do not pass the arguments object explicitly to avoid
+ // materializing it and guarantee that this function will be optimized.
+ return %NewObjectFromBound(fn, bound_args);
+ }
+
+ // Combine the args we got from the bind call with the args
+ // given as argument to the invocation.
+ var argc = %_ArgumentsLength();
+ var args = new $Array(argc + argc_bound);
+ // Add bound arguments.
+ for (var i = 0; i < argc_bound; i++) {
+ args[i] = bound_args[i];
+ }
+ // Add arguments from call.
+ for (var i = 0; i < argc; i++) {
+ args[argc_bound + i] = %_Arguments(i);
+ }
+ return fn.apply(this_arg, args);
+ };
}
- var fn = this;
- var result = function() {
- // Combine the args we got from the bind call with the args
- // given as argument to the invocation.
- var argc = %_ArgumentsLength();
- var args = new $Array(argc + argc_bound);
- // Add bound arguments.
- for (var i = 0; i < argc_bound; i++) {
- args[i] = bound_args[i];
- }
- // Add arguments from call.
- for (var i = 0; i < argc; i++) {
- args[argc_bound + i] = %_Arguments(i);
- }
- // If this is a construct call we use a special runtime method
- // to generate the actual object using the bound function.
- if (%_IsConstructCall()) {
- return %NewObjectFromBound(fn, args);
- }
- return fn.apply(this_arg, args);
- };
// We already have caller and arguments properties on functions,
// which are non-configurable. It therefore makes no sence to
diff --git a/src/version.cc b/src/version.cc
index ac1887d..912dfae 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 1
-#define BUILD_NUMBER 2
+#define BUILD_NUMBER 3
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index ef069a9..697f6cd 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -1188,6 +1188,16 @@
}
+void Assembler::imull(Register dst, const Operand& src) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ emit_optional_rex_32(dst, src);
+ emit(0x0F);
+ emit(0xAF);
+ emit_operand(dst, src);
+}
+
+
void Assembler::imull(Register dst, Register src, Immediate imm) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
@@ -3076,10 +3086,15 @@
void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
ASSERT(rmode != RelocInfo::NONE);
// Don't record external references unless the heap will be serialized.
- if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
- !Serializer::enabled() &&
- !FLAG_debug_code) {
- return;
+ if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
+#ifdef DEBUG
+ if (!Serializer::enabled()) {
+ Serializer::TooLateToEnableNow();
+ }
+#endif
+ if (!Serializer::enabled() && !FLAG_debug_code) {
+ return;
+ }
}
RelocInfo rinfo(pc_, rmode, data);
reloc_info_writer.Write(&rinfo);
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index c597783..9606e74 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -565,6 +565,8 @@
// One byte opcode for test eax,0xXXXXXXXX.
static const byte kTestEaxByte = 0xA9;
+ // One byte opcode for test al, 0xXX.
+ static const byte kTestAlByte = 0xA8;
// ---------------------------------------------------------------------------
// Code generation
@@ -863,6 +865,7 @@
void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
// Signed 32-bit multiply instructions.
void imull(Register dst, Register src); // dst = dst * src.
+ void imull(Register dst, const Operand& src); // dst = dst * src.
void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
void incq(Register dst);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index b0cadda..4b4531e 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -4627,10 +4627,10 @@
if (GetCondition() == equal) {
// For equality we do not care about the sign of the result.
- __ SmiSub(rax, rax, rdx);
+ __ subq(rax, rdx);
} else {
NearLabel done;
- __ SmiSub(rdx, rdx, rax);
+ __ subq(rdx, rax);
__ j(no_overflow, &done);
// Correct sign of result in case of overflow.
__ SmiNot(rdx, rdx);
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index b8069a2..6b63957 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -2993,21 +2993,22 @@
// Leave the frame and return popping the arguments and the
// receiver.
frame_->Exit();
- masm_->ret((scope()->num_parameters() + 1) * kPointerSize);
+ int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
+ __ Ret(arguments_bytes, rcx);
DeleteFrame();
#ifdef ENABLE_DEBUGGER_SUPPORT
// Add padding that will be overwritten by a debugger breakpoint.
- // frame_->Exit() generates "movq rsp, rbp; pop rbp; ret k"
+ // The shortest return sequence generated is "movq rsp, rbp; pop rbp; ret k"
// with length 7 (3 + 1 + 3).
const int kPadding = Assembler::kJSReturnSequenceLength - 7;
for (int i = 0; i < kPadding; ++i) {
masm_->int3();
}
- // Check that the size of the code used for returning matches what is
- // expected by the debugger.
- ASSERT_EQ(Assembler::kJSReturnSequenceLength,
- masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
+ // Check that the size of the code used for returning is large enough
+ // for the debugger's requirements.
+ ASSERT(Assembler::kJSReturnSequenceLength <=
+ masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
#endif
}
diff --git a/src/x64/cpu-x64.cc b/src/x64/cpu-x64.cc
index 30134bf..513c522 100644
--- a/src/x64/cpu-x64.cc
+++ b/src/x64/cpu-x64.cc
@@ -43,6 +43,9 @@
void CPU::Setup() {
CpuFeatures::Probe(true);
+ if (Serializer::enabled()) {
+ V8::DisableCrankshaft();
+ }
}
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 9144874..2b4bb17 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -43,6 +43,58 @@
#define __ ACCESS_MASM(masm_)
+
+class JumpPatchSite BASE_EMBEDDED {
+ public:
+ explicit JumpPatchSite(MacroAssembler* masm)
+ : masm_(masm) {
+#ifdef DEBUG
+ info_emitted_ = false;
+#endif
+ }
+
+ ~JumpPatchSite() {
+ ASSERT(patch_site_.is_bound() == info_emitted_);
+ }
+
+ void EmitJumpIfNotSmi(Register reg, NearLabel* target) {
+ __ testb(reg, Immediate(kSmiTagMask));
+ EmitJump(not_carry, target); // Always taken before patched.
+ }
+
+ void EmitJumpIfSmi(Register reg, NearLabel* target) {
+ __ testb(reg, Immediate(kSmiTagMask));
+ EmitJump(carry, target); // Never taken before patched.
+ }
+
+ void EmitPatchInfo() {
+ int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
+ ASSERT(is_int8(delta_to_patch_site));
+ __ testl(rax, Immediate(delta_to_patch_site));
+#ifdef DEBUG
+ info_emitted_ = true;
+#endif
+ }
+
+ bool is_bound() const { return patch_site_.is_bound(); }
+
+ private:
+ // jc will be patched with jz, jnc will become jnz.
+ void EmitJump(Condition cc, NearLabel* target) {
+ ASSERT(!patch_site_.is_bound() && !info_emitted_);
+ ASSERT(cc == carry || cc == not_carry);
+ __ bind(&patch_site_);
+ __ j(cc, target);
+ }
+
+ MacroAssembler* masm_;
+ Label patch_site_;
+#ifdef DEBUG
+ bool info_emitted_;
+#endif
+};
+
+
// Generate code for a JS function. On entry to the function the receiver
// and arguments have been pushed on the stack left to right, with the
// return address on top of them. The actual argument count matches the
@@ -245,19 +297,22 @@
// patch with the code required by the debugger.
__ movq(rsp, rbp);
__ pop(rbp);
- __ ret((scope()->num_parameters() + 1) * kPointerSize);
+
+ int arguments_bytes = (scope()->num_parameters() + 1) * kPointerSize;
+ __ Ret(arguments_bytes, rcx);
+
#ifdef ENABLE_DEBUGGER_SUPPORT
// Add padding that will be overwritten by a debugger breakpoint. We
- // have just generated "movq rsp, rbp; pop rbp; ret k" with length 7
+ // have just generated at least 7 bytes: "movq rsp, rbp; pop rbp; ret k"
// (3 + 1 + 3).
const int kPadding = Assembler::kJSReturnSequenceLength - 7;
for (int i = 0; i < kPadding; ++i) {
masm_->int3();
}
- // Check that the size of the code used for returning matches what is
- // expected by the debugger.
- ASSERT_EQ(Assembler::kJSReturnSequenceLength,
- masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
+ // Check that the size of the code used for returning is large enough
+ // for the debugger's requirements.
+ ASSERT(Assembler::kJSReturnSequenceLength <=
+ masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
#endif
}
}
@@ -659,18 +714,24 @@
} else if (prop != NULL) {
if (function != NULL || mode == Variable::CONST) {
// We are declaring a function or constant that rewrites to a
- // property. Use (keyed) IC to set the initial value.
- VisitForStackValue(prop->obj());
- if (function != NULL) {
- VisitForStackValue(prop->key());
- VisitForAccumulatorValue(function);
- __ pop(rcx);
- } else {
- VisitForAccumulatorValue(prop->key());
- __ movq(rcx, result_register());
- __ LoadRoot(result_register(), Heap::kTheHoleValueRootIndex);
+ // property. Use (keyed) IC to set the initial value. We
+ // cannot visit the rewrite because it's shared and we risk
+ // recording duplicate AST IDs for bailouts from optimized code.
+ ASSERT(prop->obj()->AsVariableProxy() != NULL);
+ { AccumulatorValueContext for_object(this);
+ EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
}
- __ pop(rdx);
+ if (function != NULL) {
+ __ push(rax);
+ VisitForAccumulatorValue(function);
+ __ pop(rdx);
+ } else {
+ __ movq(rdx, rax);
+ __ LoadRoot(rax, Heap::kTheHoleValueRootIndex);
+ }
+ ASSERT(prop->key()->AsLiteral() != NULL &&
+ prop->key()->AsLiteral()->handle()->IsSmi());
+ __ Move(rcx, prop->key()->AsLiteral()->handle());
Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
EmitCallIC(ic, RelocInfo::CODE_TARGET);
@@ -728,21 +789,25 @@
// Perform the comparison as if via '==='.
__ movq(rdx, Operand(rsp, 0)); // Switch value.
bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT);
+ JumpPatchSite patch_site(masm_);
if (inline_smi_code) {
- Label slow_case;
- __ JumpIfNotBothSmi(rdx, rax, &slow_case);
- __ SmiCompare(rdx, rax);
+ NearLabel slow_case;
+ __ movq(rcx, rdx);
+ __ or_(rcx, rax);
+ patch_site.EmitJumpIfNotSmi(rcx, &slow_case);
+
+ __ cmpq(rdx, rax);
__ j(not_equal, &next_test);
__ Drop(1); // Switch value is no longer needed.
__ jmp(clause->body_target()->entry_label());
__ bind(&slow_case);
}
- CompareFlags flags = inline_smi_code
- ? NO_SMI_COMPARE_IN_STUB
- : NO_COMPARE_FLAGS;
- CompareStub stub(equal, true, flags);
- __ CallStub(&stub);
+ // Record position before stub call for type feedback.
+ SetSourcePosition(clause->position());
+ Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
+ EmitCallIC(ic, &patch_site);
+
__ testq(rax, rax);
__ j(not_equal, &next_test);
__ Drop(1); // Switch value is no longer needed.
@@ -1522,16 +1587,17 @@
// Do combined smi check of the operands. Left operand is on the
// stack (popped into rdx). Right operand is in rax but moved into
// rcx to make the shifts easier.
- Label done, stub_call, smi_case;
+ NearLabel done, stub_call, smi_case;
__ pop(rdx);
__ movq(rcx, rax);
- Condition smi = masm()->CheckBothSmi(rdx, rax);
- __ j(smi, &smi_case);
+ __ or_(rax, rdx);
+ JumpPatchSite patch_site(masm_);
+ patch_site.EmitJumpIfSmi(rax, &smi_case);
__ bind(&stub_call);
- TypeRecordingBinaryOpStub stub(op, mode);
__ movq(rax, rcx);
- __ CallStub(&stub);
+ TypeRecordingBinaryOpStub stub(op, mode);
+ EmitCallIC(stub.GetCode(), &patch_site);
__ jmp(&done);
__ bind(&smi_case);
@@ -3197,7 +3263,9 @@
}
// Inline smi case if we are in a loop.
- Label stub_call, done;
+ NearLabel stub_call, done;
+ JumpPatchSite patch_site(masm_);
+
if (ShouldInlineSmiCase(expr->op())) {
if (expr->op() == Token::INC) {
__ SmiAddConstant(rax, rax, Smi::FromInt(1));
@@ -3207,8 +3275,7 @@
__ j(overflow, &stub_call);
// We could eliminate this smi check if we split the code at
// the first smi check before calling ToNumber.
- is_smi = masm_->CheckSmi(rax);
- __ j(is_smi, &done);
+ patch_site.EmitJumpIfSmi(rax, &done);
__ bind(&stub_call);
// Call stub. Undo operation first.
@@ -3230,9 +3297,9 @@
__ movq(rdx, rax);
__ Move(rax, Smi::FromInt(1));
}
- __ CallStub(&stub);
-
+ EmitCallIC(stub.GetCode(), &patch_site);
__ bind(&done);
+
// Store the value returned in rax.
switch (assign_type) {
case VARIABLE:
@@ -3500,19 +3567,21 @@
}
bool inline_smi_code = ShouldInlineSmiCase(op);
+ JumpPatchSite patch_site(masm_);
if (inline_smi_code) {
- Label slow_case;
- __ JumpIfNotBothSmi(rax, rdx, &slow_case);
- __ SmiCompare(rdx, rax);
+ NearLabel slow_case;
+ __ movq(rcx, rdx);
+ __ or_(rcx, rax);
+ patch_site.EmitJumpIfNotSmi(rcx, &slow_case);
+ __ cmpq(rdx, rax);
Split(cc, if_true, if_false, NULL);
__ bind(&slow_case);
}
- CompareFlags flags = inline_smi_code
- ? NO_SMI_COMPARE_IN_STUB
- : NO_COMPARE_FLAGS;
- CompareStub stub(cc, strict, flags);
- __ CallStub(&stub);
+ // Record position and call the compare IC.
+ SetSourcePosition(expr->position());
+ Handle<Code> ic = CompareIC::GetUninitialized(op);
+ EmitCallIC(ic, &patch_site);
PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
__ testq(rax, rax);
@@ -3575,10 +3644,30 @@
void FullCodeGenerator::EmitCallIC(Handle<Code> ic, RelocInfo::Mode mode) {
ASSERT(mode == RelocInfo::CODE_TARGET ||
mode == RelocInfo::CODE_TARGET_CONTEXT);
+ switch (ic->kind()) {
+ case Code::LOAD_IC:
+ __ IncrementCounter(&Counters::named_load_full, 1);
+ break;
+ case Code::KEYED_LOAD_IC:
+ __ IncrementCounter(&Counters::keyed_load_full, 1);
+ break;
+ case Code::STORE_IC:
+ __ IncrementCounter(&Counters::named_store_full, 1);
+ break;
+ case Code::KEYED_STORE_IC:
+ __ IncrementCounter(&Counters::keyed_store_full, 1);
+ default:
+ break;
+ }
+
__ call(ic, mode);
// Crankshaft doesn't need patching of inlined loads and stores.
- if (V8::UseCrankshaft()) return;
+ // When compiling the snapshot we need to produce code that works
+ // with and without Crankshaft.
+ if (V8::UseCrankshaft() && !Serializer::enabled()) {
+ return;
+ }
// If we're calling a (keyed) load or store stub, we have to mark
// the call as containing no inlined code so we will not attempt to
@@ -3597,6 +3686,16 @@
}
+void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
+ __ call(ic, RelocInfo::CODE_TARGET);
+ if (patch_site != NULL && patch_site->is_bound()) {
+ patch_site->EmitPatchInfo();
+ } else {
+ __ nop(); // Signals no inlined code.
+ }
+}
+
+
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
ASSERT(IsAligned(frame_offset, kPointerSize));
__ movq(Operand(rbp, frame_offset), value);
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index e5a4bfc..25f557b 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -1673,11 +1673,23 @@
}
+static bool HasInlinedSmiCode(Address address) {
+ // The address of the instruction following the call.
+ Address test_instruction_address =
+ address + Assembler::kCallTargetAddressOffset;
+
+ // If the instruction following the call is not a test al, nothing
+ // was inlined.
+ return *test_instruction_address == Assembler::kTestAlByte;
+}
+
+
void CompareIC::UpdateCaches(Handle<Object> x, Handle<Object> y) {
HandleScope scope;
Handle<Code> rewritten;
State previous_state = GetState();
- State state = TargetState(previous_state, false, x, y);
+
+ State state = TargetState(previous_state, HasInlinedSmiCode(address()), x, y);
if (state == GENERIC) {
CompareStub stub(GetCondition(), strict(), NO_COMPARE_FLAGS);
rewritten = stub.GetCode();
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 48d4130..a1f8cb4 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -593,7 +593,56 @@
void LCodeGen::DoCallStub(LCallStub* instr) {
- Abort("Unimplemented: %s", "DoCallStub");
+ ASSERT(ToRegister(instr->result()).is(rax));
+ switch (instr->hydrogen()->major_key()) {
+ case CodeStub::RegExpConstructResult: {
+ RegExpConstructResultStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::RegExpExec: {
+ RegExpExecStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::SubString: {
+ SubStringStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringCharAt: {
+ // TODO(1116): Add StringCharAt stub to x64.
+ Abort("Unimplemented: %s", "StringCharAt Stub");
+ break;
+ }
+ case CodeStub::MathPow: {
+ // TODO(1115): Add MathPow stub to x64.
+ Abort("Unimplemented: %s", "MathPow Stub");
+ break;
+ }
+ case CodeStub::NumberToString: {
+ NumberToStringStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringAdd: {
+ StringAddStub stub(NO_STRING_ADD_FLAGS);
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::StringCompare: {
+ StringCompareStub stub;
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ case CodeStub::TranscendentalCache: {
+ TranscendentalCacheStub stub(instr->transcendental_type());
+ CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
}
@@ -608,11 +657,92 @@
void LCodeGen::DoDivI(LDivI* instr) {
- Abort("Unimplemented: %s", "DoDivI");}
+ LOperand* right = instr->InputAt(1);
+ ASSERT(ToRegister(instr->result()).is(rax));
+ ASSERT(ToRegister(instr->InputAt(0)).is(rax));
+ ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
+ ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
+
+ Register left_reg = rax;
+
+ // Check for x / 0.
+ Register right_reg = ToRegister(right);
+ if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+ __ testl(right_reg, right_reg);
+ DeoptimizeIf(zero, instr->environment());
+ }
+
+ // Check for (0 / -x) that will produce negative zero.
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ NearLabel left_not_zero;
+ __ testl(left_reg, left_reg);
+ __ j(not_zero, &left_not_zero);
+ __ testl(right_reg, right_reg);
+ DeoptimizeIf(sign, instr->environment());
+ __ bind(&left_not_zero);
+ }
+
+ // Check for (-kMinInt / -1).
+ if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ NearLabel left_not_min_int;
+ __ cmpl(left_reg, Immediate(kMinInt));
+ __ j(not_zero, &left_not_min_int);
+ __ cmpl(right_reg, Immediate(-1));
+ DeoptimizeIf(zero, instr->environment());
+ __ bind(&left_not_min_int);
+ }
+
+ // Sign extend to rdx.
+ __ cdq();
+ __ idivl(right_reg);
+
+ // Deoptimize if remainder is not 0.
+ __ testl(rdx, rdx);
+ DeoptimizeIf(not_zero, instr->environment());
+}
void LCodeGen::DoMulI(LMulI* instr) {
- Abort("Unimplemented: %s", "DoMultI");}
+ Register left = ToRegister(instr->InputAt(0));
+ LOperand* right = instr->InputAt(1);
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ __ movl(kScratchRegister, left);
+ }
+
+ if (right->IsConstantOperand()) {
+ int right_value = ToInteger32(LConstantOperand::cast(right));
+ __ imull(left, left, Immediate(right_value));
+ } else if (right->IsStackSlot()) {
+ __ imull(left, ToOperand(right));
+ } else {
+ __ imull(left, ToRegister(right));
+ }
+
+ if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ DeoptimizeIf(overflow, instr->environment());
+ }
+
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ // Bail out if the result is supposed to be negative zero.
+ NearLabel done;
+ __ testl(left, left);
+ __ j(not_zero, &done);
+ if (right->IsConstantOperand()) {
+ if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
+ DeoptimizeIf(no_condition, instr->environment());
+ }
+ } else if (right->IsStackSlot()) {
+ __ or_(kScratchRegister, ToOperand(right));
+ DeoptimizeIf(sign, instr->environment());
+ } else {
+ // Test the non-zero operand for negative sign.
+ __ or_(kScratchRegister, ToRegister(right));
+ DeoptimizeIf(sign, instr->environment());
+ }
+ __ bind(&done);
+ }
+}
void LCodeGen::DoBitI(LBitI* instr) {
@@ -810,7 +940,13 @@
void LCodeGen::DoThrow(LThrow* instr) {
- Abort("Unimplemented: %s", "DoThrow");
+ __ push(ToRegister(instr->InputAt(0)));
+ CallRuntime(Runtime::kThrow, 1, instr);
+
+ if (FLAG_debug_code) {
+ Comment("Unreachable code.");
+ __ int3();
+ }
}
@@ -844,8 +980,7 @@
ASSERT(ToRegister(instr->InputAt(1)).is(rax));
ASSERT(ToRegister(instr->result()).is(rax));
- GenericBinaryOpStub stub(instr->op(), NO_OVERWRITE, NO_GENERIC_BINARY_FLAGS);
- stub.SetArgsInRegisters();
+ TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE);
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
}
@@ -963,7 +1098,11 @@
void LCodeGen::DoDeferredStackCheck(LGoto* instr) {
- Abort("Unimplemented: %s", "DoDeferredStackCheck");
+ __ Pushad();
+ __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
+ RecordSafepointWithRegisters(
+ instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex);
+ __ Popad();
}
@@ -1022,9 +1161,9 @@
__ cmpl(ToOperand(left), Immediate(value));
}
} else if (right->IsRegister()) {
- __ cmpq(ToRegister(left), ToRegister(right));
+ __ cmpl(ToRegister(left), ToRegister(right));
} else {
- __ cmpq(ToRegister(left), ToOperand(right));
+ __ cmpl(ToRegister(left), ToOperand(right));
}
}
@@ -1511,12 +1650,23 @@
}
__ movq(rsp, rbp);
__ pop(rbp);
- __ ret((ParameterCount() + 1) * kPointerSize);
+ __ Ret((ParameterCount() + 1) * kPointerSize, rcx);
}
void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) {
- Abort("Unimplemented: %s", "DoLoadGlobal");
+ Register result = ToRegister(instr->result());
+ if (result.is(rax)) {
+ __ load_rax(instr->hydrogen()->cell().location(),
+ RelocInfo::GLOBAL_PROPERTY_CELL);
+ } else {
+ __ movq(result, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL);
+ __ movq(result, Operand(result, 0));
+ }
+ if (instr->hydrogen()->check_hole_value()) {
+ __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
+ DeoptimizeIf(equal, instr->environment());
+ }
}
@@ -1534,9 +1684,7 @@
// been deleted from the property dictionary. In that case, we need
// to update the property details in the property dictionary to mark
// it as no longer deleted. We deoptimize in that case.
- __ movq(temp,
- Handle<Object>::cast(instr->hydrogen()->cell()),
- RelocInfo::GLOBAL_PROPERTY_CELL);
+ __ movq(temp, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL);
if (check_hole) {
__ CompareRoot(Operand(temp, 0), Heap::kTheHoleValueRootIndex);
DeoptimizeIf(equal, instr->environment());
@@ -1563,7 +1711,12 @@
void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
- Abort("Unimplemented: %s", "DoLoadNamedGeneric");
+ ASSERT(ToRegister(instr->object()).is(rax));
+ ASSERT(ToRegister(instr->result()).is(rax));
+
+ __ Move(rcx, instr->name());
+ Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
+ CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -1855,7 +2008,33 @@
void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
- Abort("Unimplemented: %s", "DoStoreKeyedFastElement");
+ Register value = ToRegister(instr->value());
+ Register elements = ToRegister(instr->object());
+ Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
+
+ // Do the store.
+ if (instr->key()->IsConstantOperand()) {
+ ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
+ LConstantOperand* const_operand = LConstantOperand::cast(instr->key());
+ int offset =
+ ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize;
+ __ movq(FieldOperand(elements, offset), value);
+ } else {
+ __ movq(FieldOperand(elements,
+ key,
+ times_pointer_size,
+ FixedArray::kHeaderSize),
+ value);
+ }
+
+ if (instr->hydrogen()->NeedsWriteBarrier()) {
+ // Compute address of modified element and store it into key register.
+ __ lea(key, FieldOperand(elements,
+ key,
+ times_pointer_size,
+ FixedArray::kHeaderSize));
+ __ RecordWrite(elements, key, value);
+ }
}
@@ -1926,12 +2105,21 @@
void LCodeGen::DoSmiTag(LSmiTag* instr) {
- Abort("Unimplemented: %s", "DoSmiTag");
+ ASSERT(instr->InputAt(0)->Equals(instr->result()));
+ Register input = ToRegister(instr->InputAt(0));
+ ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
+ __ Integer32ToSmi(input, input);
}
void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
- Abort("Unimplemented: %s", "DoSmiUntag");
+ ASSERT(instr->InputAt(0)->Equals(instr->result()));
+ Register input = ToRegister(instr->InputAt(0));
+ if (instr->needs_check()) {
+ Condition is_smi = __ CheckSmi(input);
+ DeoptimizeIf(NegateCondition(is_smi), instr->environment());
+ }
+ __ SmiToInteger32(input, input);
}
@@ -2110,7 +2298,14 @@
void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
- Abort("Unimplemented: %s", "LoadHeapObject");
+ if (Heap::InNewSpace(*object)) {
+ Handle<JSGlobalPropertyCell> cell =
+ Factory::NewJSGlobalPropertyCell(object);
+ __ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
+ __ movq(result, Operand(result, 0));
+ } else {
+ __ Move(result, object);
+ }
}
@@ -2219,6 +2414,54 @@
}
+void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) {
+ Register result = ToRegister(instr->result());
+ NearLabel true_label;
+ NearLabel false_label;
+ NearLabel done;
+
+ EmitIsConstructCall(result);
+ __ j(equal, &true_label);
+
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ jmp(&done);
+
+ __ bind(&true_label);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+
+
+ __ bind(&done);
+}
+
+
+void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
+ Register temp = ToRegister(instr->TempAt(0));
+ int true_block = chunk_->LookupDestination(instr->true_block_id());
+ int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+ EmitIsConstructCall(temp);
+ EmitBranch(true_block, false_block, equal);
+}
+
+
+void LCodeGen::EmitIsConstructCall(Register temp) {
+ // Get the frame pointer for the calling frame.
+ __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
+
+ // Skip the arguments adaptor frame if it exists.
+ NearLabel check_frame_marker;
+ __ SmiCompare(Operand(temp, StandardFrameConstants::kContextOffset),
+ Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
+ __ j(not_equal, &check_frame_marker);
+ __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset));
+
+ // Check the marker in the calling frame.
+ __ bind(&check_frame_marker);
+ __ SmiCompare(Operand(temp, StandardFrameConstants::kMarkerOffset),
+ Smi::FromInt(StackFrame::CONSTRUCT));
+}
+
+
void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
Register input = ToRegister(instr->InputAt(0));
int true_block = chunk_->LookupDestination(instr->true_block_id());
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index cbcc5c8..6f8f06e 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -221,6 +221,10 @@
Label* is_not_object,
Label* is_object);
+ // Emits optimized code for %_IsConstructCall().
+ // Caller should branch on equal condition.
+ void EmitIsConstructCall(Register temp);
+
LChunk* const chunk_;
MacroAssembler* const masm_;
CompilationInfo* const info_;
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 12b952d..56b991d 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1082,6 +1082,8 @@
} else if (v->IsTypeofIs()) {
HTypeofIs* typeof_is = HTypeofIs::cast(v);
return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()));
+ } else if (v->IsIsConstructCall()) {
+ return new LIsConstructCallAndBranch(TempRegister());
} else {
if (v->IsConstant()) {
if (HConstant::cast(v)->handle()->IsTrue()) {
@@ -1262,8 +1264,20 @@
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
- Abort("Unimplemented: %s", "DoDiv");
- return NULL;
+ if (instr->representation().IsDouble()) {
+ return DoArithmeticD(Token::DIV, instr);
+ } else if (instr->representation().IsInteger32()) {
+ // The temporary operand is necessary to ensure that right is not allocated
+ // into rdx.
+ LOperand* temp = FixedTemp(rdx);
+ LOperand* dividend = UseFixed(instr->left(), rax);
+ LOperand* divisor = UseRegister(instr->right());
+ LDivI* result = new LDivI(dividend, divisor, temp);
+ return AssignEnvironment(DefineFixed(result, rax));
+ } else {
+ ASSERT(instr->representation().IsTagged());
+ return DoArithmeticT(Token::DIV, instr);
+ }
}
@@ -1274,8 +1288,19 @@
LInstruction* LChunkBuilder::DoMul(HMul* instr) {
- Abort("Unimplemented: %s", "DoMul");
- return NULL;
+ if (instr->representation().IsInteger32()) {
+ ASSERT(instr->left()->representation().IsInteger32());
+ ASSERT(instr->right()->representation().IsInteger32());
+ LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
+ LOperand* right = UseOrConstant(instr->MostConstantOperand());
+ LMulI* mul = new LMulI(left, right);
+ return AssignEnvironment(DefineSameAsFirst(mul));
+ } else if (instr->representation().IsDouble()) {
+ return DoArithmeticD(Token::MUL, instr);
+ } else {
+ ASSERT(instr->representation().IsTagged());
+ return DoArithmeticT(Token::MUL, instr);
+ }
}
@@ -1439,8 +1464,8 @@
LInstruction* LChunkBuilder::DoThrow(HThrow* instr) {
- Abort("Unimplemented: %s", "DoThrow");
- return NULL;
+ LOperand* value = UseFixed(instr->value(), rax);
+ return MarkAsCall(new LThrow(value), instr);
}
@@ -1552,14 +1577,12 @@
LInstruction* LChunkBuilder::DoConstant(HConstant* instr) {
Representation r = instr->representation();
if (r.IsInteger32()) {
- int32_t value = instr->Integer32Value();
- return DefineAsRegister(new LConstantI(value));
+ return DefineAsRegister(new LConstantI);
} else if (r.IsDouble()) {
- double value = instr->DoubleValue();
LOperand* temp = TempRegister();
- return DefineAsRegister(new LConstantD(value, temp));
+ return DefineAsRegister(new LConstantD(temp));
} else if (r.IsTagged()) {
- return DefineAsRegister(new LConstantT(instr->handle()));
+ return DefineAsRegister(new LConstantT);
} else {
UNREACHABLE();
return NULL;
@@ -1602,8 +1625,9 @@
LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) {
- Abort("Unimplemented: %s", "DoLoadNamedGeneric");
- return NULL;
+ LOperand* object = UseFixed(instr->object(), rax);
+ LLoadNamedGeneric* result = new LLoadNamedGeneric(object);
+ return MarkAsCall(DefineFixed(result, rax), instr);
}
@@ -1639,8 +1663,20 @@
LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
HStoreKeyedFastElement* instr) {
- Abort("Unimplemented: %s", "DoStoreKeyedFastElement");
- return NULL;
+ bool needs_write_barrier = instr->NeedsWriteBarrier();
+ ASSERT(instr->value()->representation().IsTagged());
+ ASSERT(instr->object()->representation().IsTagged());
+ ASSERT(instr->key()->representation().IsInteger32());
+
+ LOperand* obj = UseTempRegister(instr->object());
+ LOperand* val = needs_write_barrier
+ ? UseTempRegister(instr->value())
+ : UseRegisterAtStart(instr->value());
+ LOperand* key = needs_write_barrier
+ ? UseTempRegister(instr->key())
+ : UseRegisterOrConstantAtStart(instr->key());
+
+ return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val));
}
@@ -1734,8 +1770,8 @@
LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) {
- Abort("Unimplemented: %s", "DoCallStub");
- return NULL;
+ argument_count_ -= instr->argument_count();
+ return MarkAsCall(DefineFixed(new LCallStub, rax), instr);
}
@@ -1762,6 +1798,12 @@
return NULL;
}
+
+LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) {
+ return DefineAsRegister(new LIsConstructCall);
+}
+
+
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
HEnvironment* env = current_block_->last_environment();
ASSERT(env != NULL);
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 64d141e..331824f 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -39,119 +39,8 @@
// Forward declarations.
class LCodeGen;
-
-// Type hierarchy:
-//
-// LInstruction
-// LTemplateInstruction
-// LControlInstruction
-// LBranch
-// LClassOfTestAndBranch
-// LCmpJSObjectEqAndBranch
-// LCmpIDAndBranch
-// LHasCachedArrayIndexAndBranch
-// LHasInstanceTypeAndBranch
-// LInstanceOfAndBranch
-// LIsNullAndBranch
-// LIsObjectAndBranch
-// LIsSmiAndBranch
-// LTypeofIsAndBranch
-// LAccessArgumentsAt
-// LArgumentsElements
-// LArgumentsLength
-// LAddI
-// LApplyArguments
-// LArithmeticD
-// LArithmeticT
-// LBitI
-// LBoundsCheck
-// LCmpID
-// LCmpJSObjectEq
-// LCmpT
-// LDivI
-// LInstanceOf
-// LInstanceOfKnownGlobal
-// LLoadKeyedFastElement
-// LLoadKeyedGeneric
-// LModI
-// LMulI
-// LPower
-// LShiftI
-// LSubI
-// LCallConstantFunction
-// LCallFunction
-// LCallGlobal
-// LCallKeyed
-// LCallKnownGlobal
-// LCallNamed
-// LCallRuntime
-// LCallStub
-// LConstant
-// LConstantD
-// LConstantI
-// LConstantT
-// LDeoptimize
-// LFunctionLiteral
-// LGap
-// LLabel
-// LGlobalObject
-// LGlobalReceiver
-// LGoto
-// LLazyBailout
-// LLoadGlobal
-// LCheckPrototypeMaps
-// LLoadContextSlot
-// LArrayLiteral
-// LObjectLiteral
-// LRegExpLiteral
-// LOsrEntry
-// LParameter
-// LRegExpConstructResult
-// LStackCheck
-// LStoreKeyed
-// LStoreKeyedFastElement
-// LStoreKeyedGeneric
-// LStoreNamed
-// LStoreNamedField
-// LStoreNamedGeneric
-// LBitNotI
-// LCallNew
-// LCheckFunction
-// LCheckPrototypeMaps
-// LCheckInstanceType
-// LCheckMap
-// LCheckSmi
-// LClassOfTest
-// LDeleteProperty
-// LDoubleToI
-// LFixedArrayLength
-// LHasCachedArrayIndex
-// LHasInstanceType
-// LInteger32ToDouble
-// LIsNull
-// LIsObject
-// LIsSmi
-// LJSArrayLength
-// LLoadNamedField
-// LLoadNamedGeneric
-// LLoadFunctionPrototype
-// LNumberTagD
-// LNumberTagI
-// LPushArgument
-// LReturn
-// LSmiTag
-// LStoreGlobal
-// LTaggedToI
-// LThrow
-// LTypeof
-// LTypeofIs
-// LUnaryMathOperation
-// LValueOf
-// LUnknownOSRValue
-
#define LITHIUM_ALL_INSTRUCTION_LIST(V) \
V(ControlInstruction) \
- V(Constant) \
V(Call) \
V(StoreKeyed) \
V(StoreNamed) \
@@ -259,6 +148,8 @@
V(Typeof) \
V(TypeofIs) \
V(TypeofIsAndBranch) \
+ V(IsConstructCall) \
+ V(IsConstructCallAndBranch) \
V(UnaryMathOperation) \
V(UnknownOSRValue) \
V(ValueOf)
@@ -648,12 +539,11 @@
};
-class LMulI: public LTemplateInstruction<1, 2, 1> {
+class LMulI: public LTemplateInstruction<1, 2, 0> {
public:
- LMulI(LOperand* left, LOperand* right, LOperand* temp) {
+ LMulI(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
- temps_[0] = temp;
}
DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
@@ -1013,47 +903,33 @@
};
-template <int temp_count>
-class LConstant: public LTemplateInstruction<1, 0, temp_count> {
- DECLARE_INSTRUCTION(Constant)
-};
-
-
-class LConstantI: public LConstant<0> {
+class LConstantI: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantI(int32_t value) : value_(value) { }
- int32_t value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantI, "constant-i")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- int32_t value_;
+ int32_t value() const { return hydrogen()->Integer32Value(); }
};
-class LConstantD: public LConstant<1> {
+class LConstantD: public LTemplateInstruction<1, 0, 1> {
public:
- explicit LConstantD(double value, LOperand* temp) : value_(value) {
+ explicit LConstantD(LOperand* temp) {
temps_[0] = temp;
}
- double value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantD, "constant-d")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- double value_;
+ double value() const { return hydrogen()->DoubleValue(); }
};
-class LConstantT: public LConstant<0> {
+class LConstantT: public LTemplateInstruction<1, 0, 0> {
public:
- explicit LConstantT(Handle<Object> value) : value_(value) { }
- Handle<Object> value() const { return value_; }
-
DECLARE_CONCRETE_INSTRUCTION(ConstantT, "constant-t")
+ DECLARE_HYDROGEN_ACCESSOR(Constant)
- private:
- Handle<Object> value_;
+ Handle<Object> value() const { return hydrogen()->handle(); }
};
@@ -1763,6 +1639,24 @@
};
+class LIsConstructCall: public LTemplateInstruction<1, 0, 0> {
+ public:
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCall, "is-construct-call")
+ DECLARE_HYDROGEN_ACCESSOR(IsConstructCall)
+};
+
+
+class LIsConstructCallAndBranch: public LControlInstruction<0, 1> {
+ public:
+ explicit LIsConstructCallAndBranch(LOperand* temp) {
+ temps_[0] = temp;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(IsConstructCallAndBranch,
+ "is-construct-call-and-branch")
+};
+
+
class LDeleteProperty: public LTemplateInstruction<1, 2, 0> {
public:
LDeleteProperty(LOperand* obj, LOperand* key) {
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 50b689b..56a2d6f 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -1541,6 +1541,18 @@
}
+void MacroAssembler::Ret(int bytes_dropped, Register scratch) {
+ if (is_uint16(bytes_dropped)) {
+ ret(bytes_dropped);
+ } else {
+ pop(scratch);
+ addq(rsp, Immediate(bytes_dropped));
+ push(scratch);
+ ret(0);
+ }
+}
+
+
void MacroAssembler::FCmp() {
fucomip();
fstp(0);
@@ -2098,11 +2110,11 @@
Register top_reg = result_end.is_valid() ? result_end : result;
- if (top_reg.is(result)) {
- addq(top_reg, Immediate(object_size));
- } else {
- lea(top_reg, Operand(result, object_size));
+ if (!top_reg.is(result)) {
+ movq(top_reg, result);
}
+ addq(top_reg, Immediate(object_size));
+ j(carry, gc_required);
movq(kScratchRegister, new_space_allocation_limit);
cmpq(top_reg, Operand(kScratchRegister, 0));
j(above, gc_required);
@@ -2152,7 +2164,12 @@
// Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit =
ExternalReference::new_space_allocation_limit_address();
- lea(result_end, Operand(result, element_count, element_size, header_size));
+
+ // We assume that element_count*element_size + header_size does not
+ // overflow.
+ lea(result_end, Operand(element_count, element_size, header_size));
+ addq(result_end, result);
+ j(carry, gc_required);
movq(kScratchRegister, new_space_allocation_limit);
cmpq(result_end, Operand(kScratchRegister, 0));
j(above, gc_required);
@@ -2198,6 +2215,7 @@
movq(result_end, object_size);
}
addq(result_end, result);
+ j(carry, gc_required);
movq(kScratchRegister, new_space_allocation_limit);
cmpq(result_end, Operand(kScratchRegister, 0));
j(above, gc_required);
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 8bb3190..1002635 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -920,6 +920,10 @@
void Ret();
+ // Return and drop arguments from stack, where the number of arguments
+ // may be bigger than 2^16 - 1. Requires a scratch register.
+ void Ret(int bytes_dropped, Register scratch);
+
Handle<Object> CodeObject() { return code_object_; }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index f88ba38..970fdaa 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -12549,3 +12549,19 @@
CHECK_EQ(1, result->Length());
CHECK_EQ(v8_str("universalAnswer"), result->Get(0));
}
+
+
+TEST(DefinePropertyPostDetach) {
+ v8::HandleScope scope;
+ LocalContext context;
+ v8::Handle<v8::Object> proxy = context->Global();
+ v8::Handle<v8::Function> define_property =
+ CompileRun("(function() {"
+ " Object.defineProperty("
+ " this,"
+ " 1,"
+ " { configurable: true, enumerable: true, value: 3 });"
+ "})").As<Function>();
+ context->DetachGlobal();
+ define_property->Call(proxy, 0, NULL);
+}
diff --git a/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index 30d708e..c995aa8 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -446,6 +446,14 @@
}
}
+ {
+ if (CpuFeatures::IsSupported(SSE4_1)) {
+ CpuFeatures::Scope scope(SSE4_1);
+ __ pextrd(Operand(eax), xmm0, 1);
+ __ pinsrd(xmm1, Operand(eax), 0);
+ }
+ }
+
__ ret(0);
CodeDesc desc;
diff --git a/test/cctest/test-strtod.cc b/test/cctest/test-strtod.cc
index f5547db..da6b07b 100644
--- a/test/cctest/test-strtod.cc
+++ b/test/cctest/test-strtod.cc
@@ -324,6 +324,25 @@
StrtodChar("5708990770823839207320493820740630171355185151999", -3));
CHECK_EQ(5708990770823839524233143877797980545530986496.0,
StrtodChar("5708990770823839207320493820740630171355185152001", -3));
+
+ // The following test-cases got some public attention in early 2011 when they
+ // sent Java and PHP into an infinite loop.
+ CHECK_EQ(2.225073858507201e-308, StrtodChar("22250738585072011", -324));
+ CHECK_EQ(2.22507385850720138309e-308,
+ StrtodChar("22250738585072011360574097967091319759348195463516456480"
+ "23426109724822222021076945516529523908135087914149158913"
+ "03962110687008643869459464552765720740782062174337998814"
+ "10632673292535522868813721490129811224514518898490572223"
+ "07285255133155755015914397476397983411801999323962548289"
+ "01710708185069063066665599493827577257201576306269066333"
+ "26475653000092458883164330377797918696120494973903778297"
+ "04905051080609940730262937128958950003583799967207254304"
+ "36028407889577179615094551674824347103070260914462157228"
+ "98802581825451803257070188608721131280795122334262883686"
+ "22321503775666622503982534335974568884423900265498198385"
+ "48794829220689472168983109969836584681402285424333066033"
+ "98508864458040010349339704275671864433837704860378616227"
+ "71738545623065874679014086723327636718751", -1076));
}
diff --git a/test/es5conform/es5conform.status b/test/es5conform/es5conform.status
index 0dd2750..434f9d1 100644
--- a/test/es5conform/es5conform.status
+++ b/test/es5conform/es5conform.status
@@ -234,7 +234,8 @@
# Setting expectations to fail only so that the tests trigger as soon as
# the strict mode feature gets implemented
-# A directive preceeding an 'use strict' directive may not contain an OctalEscapeSequence
+# A directive preceeding an 'use strict' directive may not contain
+# an OctalEscapeSequence
# Incorrect test - need double escape in eval.
chapter07/7.8/7.8.4/7.8.4-1-s: FAIL
@@ -263,134 +264,180 @@
# arguments.callee is non-configurable in strict mode
chapter10/10.6/10.6-13-c-3-s: FAIL
-# simple assignment throws ReferenceError if LeftHandSide is an unresolvable reference in strict mode
+# simple assignment throws ReferenceError if LeftHandSide is an unresolvable
+# reference in strict mode
chapter11/11.13/11.13.1/11.13.1-1-5-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a property reference with a primitive base value (this is undefined)
+# simple assignment throws TypeError if LeftHandSide is a property reference
+# with a primitive base value (this is undefined)
chapter11/11.13/11.13.1/11.13.1-1-7-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Global.NaN)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Global.NaN)
chapter11/11.13/11.13.1/11.13.1-4-2-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Global.Infinity)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Global.Infinity)
chapter11/11.13/11.13.1/11.13.1-4-3-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Global.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Global.length)
chapter11/11.13/11.13.1/11.13.1-4-4-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Object.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Object.length)
chapter11/11.13/11.13.1/11.13.1-4-5-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Function.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Function.length)
chapter11/11.13/11.13.1/11.13.1-4-6-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Array.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Array.length)
chapter11/11.13/11.13.1/11.13.1-4-7-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (String.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (String.length)
chapter11/11.13/11.13.1/11.13.1-4-8-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Boolean.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Boolean.length)
chapter11/11.13/11.13.1/11.13.1-4-9-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Number.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Number.length)
chapter11/11.13/11.13.1/11.13.1-4-10-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Date.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Date.length)
chapter11/11.13/11.13.1/11.13.1-4-11-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (RegExp.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (RegExp.length)
chapter11/11.13/11.13.1/11.13.1-4-12-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Error.length)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Error.length)
chapter11/11.13/11.13.1/11.13.1-4-13-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Number.MAX_VALUE)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Number.MAX_VALUE)
chapter11/11.13/11.13.1/11.13.1-4-14-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Number.MIN_VALUE)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Number.MIN_VALUE)
chapter11/11.13/11.13.1/11.13.1-4-15-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Number.NaN)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Number.NaN)
chapter11/11.13/11.13.1/11.13.1-4-16-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Number.NEGATIVE_INFINITY)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Number.NEGATIVE_INFINITY)
chapter11/11.13/11.13.1/11.13.1-4-17-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Number.POSITIVE_INFINITY)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Number.POSITIVE_INFINITY)
chapter11/11.13/11.13.1/11.13.1-4-18-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.E)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.E)
chapter11/11.13/11.13.1/11.13.1-4-19-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.LN10)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.LN10)
chapter11/11.13/11.13.1/11.13.1-4-20-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.LN2)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.LN2)
chapter11/11.13/11.13.1/11.13.1-4-21-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.LOG2E)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.LOG2E)
chapter11/11.13/11.13.1/11.13.1-4-22-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.LOG10E)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.LOG10E)
chapter11/11.13/11.13.1/11.13.1-4-23-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.PI)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.PI)
chapter11/11.13/11.13.1/11.13.1-4-24-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.SQRT1_2)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.SQRT1_2)
chapter11/11.13/11.13.1/11.13.1-4-25-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Math.SQRT2)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Math.SQRT2)
chapter11/11.13/11.13.1/11.13.1-4-26-s: FAIL
-# simple assignment throws TypeError if LeftHandSide is a readonly property in strict mode (Global.undefined)
+# simple assignment throws TypeError if LeftHandSide is a readonly property
+# in strict mode (Global.undefined)
chapter11/11.13/11.13.1/11.13.1-4-27-s: FAIL
-# delete operator throws TypeError when deleting a non-configurable data property in strict mode
+# delete operator throws TypeError when deleting a non-configurable data
+# property in strict mode
chapter11/11.4/11.4.1/11.4.1-4.a-3-s: FAIL
-# delete operator throws TypeError when when deleting a non-configurable data property in strict mode (Global.NaN)
+# delete operator throws TypeError when when deleting a non-configurable
+# data property in strict mode (Global.NaN)
chapter11/11.4/11.4.1/11.4.1-4.a-4-s: FAIL
-# delete operator throws TypeError when deleting a non-configurable data property in strict mode (Math.LN2)
+# delete operator throws TypeError when deleting a non-configurable data
+# property in strict mode (Math.LN2)
chapter11/11.4/11.4.1/11.4.1-4.a-9-s: FAIL
-# delete operator throws ReferenceError when deleting a direct reference to a var in strict mode
+# delete operator throws ReferenceError when deleting a direct reference
+# to a var in strict mode
chapter11/11.4/11.4.1/11.4.1-5-1-s: FAIL
-# delete operator throws ReferenceError when deleting a direct reference to a function argument in strict mode
+# delete operator throws ReferenceError when deleting a direct reference
+# to a function argument in strict mode
chapter11/11.4/11.4.1/11.4.1-5-2-s: FAIL
-# delete operator throws ReferenceError when deleting a direct reference to a function name in strict mode
+# delete operator throws ReferenceError when deleting a direct reference
+# to a function name in strict mode
chapter11/11.4/11.4.1/11.4.1-5-3-s: FAIL
-# delete operator throws SyntaxError when deleting a direct reference to a function argument(object) in strict mode
+# delete operator throws SyntaxError when deleting a direct reference
+# to a function argument(object) in strict mode
chapter11/11.4/11.4.1/11.4.1-5-4-s: FAIL
# eval - a function declaring a var named 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-1-s: FAIL
# eval - a function assigning into 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-2-s: FAIL
-# eval - a function expr declaring a var named 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# eval - a function expr declaring a var named 'eval' throws EvalError
+# in strict mode
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-3-s: FAIL
# eval - a function expr assigning into 'eval' throws a EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-4-s: FAIL
# eval - a Function declaring var named 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-5-s: FAIL
# eval - a Function assigning into 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-6-s: FAIL
-# eval - a direct eval declaring a var named 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# eval - a direct eval declaring a var named 'eval' throws EvalError
+# in strict mode
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-7-s: FAIL
# eval - a direct eval assigning into 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-8-s: FAIL
-# eval - an indirect eval declaring a var named 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# eval - an indirect eval declaring a var named 'eval' throws EvalError
+# in strict mode
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-9-s: FAIL
# eval - an indirect eval assigning into 'eval' throws EvalError in strict mode
-# EvalError - incorrect test (SyntaxError should be expected instead of EvalError)
+# Invalid test case. SyntaxError should be expected instead of EvalError.
chapter12/12.2/12.2.1/12.2.1-10-s: FAIL
-# SyntaxError if eval used as function identifier in function declaration with strict body
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if eval used as function identifier in function declaration
+# with strict body
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-3-s: FAIL
-# SyntaxError if eval used as function identifier in function expression with strict body
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if eval used as function identifier in function expression
+# with strict body
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-4-s: FAIL
-# SyntaxError if eval used as function identifier in function declaration in strict code
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if eval used as function identifier in function declaration
+# in strict code
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-5-s: FAIL
-# SyntaxError if eval used as function identifier in function expression in strict code
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if eval used as function identifier in function expression
+# in strict code
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-6-s: FAIL
-# SyntaxError if arguments used as function identifier in function declaration with strict body
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if arguments used as function identifier in function declaration
+# with strict body
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-9-s: FAIL
-# SyntaxError if arguments used as function identifier in function expression with strict body
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if arguments used as function identifier in function expression
+# with strict body
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-10-s: FAIL
-# SyntaxError if arguments used as function identifier in function declaration in strict code
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if arguments used as function identifier in function declaration
+# in strict code
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-11-s: FAIL
-# SyntaxError if arguments used as function identifier in function expression in strict code
-# test uses implicit return (which doesn't seem to work in v8 or safari jsc)
+# SyntaxError if arguments used as function identifier in function expression
+# in strict code
+# Test fails to return true on success (invalid test case).
chapter13/13.1/13.1-3-12-s: FAIL
# 'use strict' directive - correct usage
@@ -424,8 +471,9 @@
# depends on "this is not coerced to an object in strict mode (undefined)"
chapter14/14.1/14.1-15-s: FAIL
-# Duplicate combined parameter name allowed in Function constructor called in strict mode if body not strict
-# Invalid test case per ECMA-262 5th Edition, 10.1.1, bullet 4
+# Duplicate combined parameter name allowed in Function constructor called
+# in strict mode if body not strict
+# Test fails to return true on success (invalid test case).
chapter15/15.3/15.3.2/15.3.2.1/15.3.2.1-11-6-s: FAIL
# Array.prototype.every - thisArg not passed to strict callbackfn
diff --git a/test/mjsunit/getter-in-prototype.js b/test/mjsunit/getter-in-prototype.js
index dd26c53..5563123 100644
--- a/test/mjsunit/getter-in-prototype.js
+++ b/test/mjsunit/getter-in-prototype.js
@@ -31,9 +31,11 @@
var o = {};
var p = {};
p.__defineGetter__('x', function(){});
+p.__defineGetter__(0, function(){});
o.__proto__ = p;
assertThrows("o.x = 42");
+assertThrows("o[0] = 42");
function f() {
with(o) {
@@ -48,3 +50,9 @@
x = 42;
}
assertThrows("g()");
+
+__proto__ = p;
+function g2() {
+ this[0] = 42;
+}
+assertThrows("g2()");
diff --git a/test/mjsunit/json.js b/test/mjsunit/json.js
index a0be8dd..812ffeb 100644
--- a/test/mjsunit/json.js
+++ b/test/mjsunit/json.js
@@ -415,3 +415,17 @@
falseNum.__proto__ = Number.prototype;
falseNum.toString = function() { return 42; };
assertEquals('"42"', JSON.stringify(falseNum));
+
+// We don't currently allow plain properties called __proto__ in JSON
+// objects in JSON.parse. Instead we read them as we would JS object
+// literals. If we change that, this test should change with it.
+//
+// Parse a non-object value as __proto__. This must not create a
+// __proto__ property different from the original, and should not
+// change the original.
+var o = JSON.parse('{"__proto__":5}');
+assertEquals(Object.prototype, o.__proto__); // __proto__ isn't changed.
+assertEquals(0, Object.keys(o).length); // __proto__ isn't added as enumerable.
+
+
+
diff --git a/test/mjsunit/regress/regress-1103.js b/test/mjsunit/regress/regress-1103.js
new file mode 100644
index 0000000..4ad25b3
--- /dev/null
+++ b/test/mjsunit/regress/regress-1103.js
@@ -0,0 +1,32 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that freezing the global object functions correctly and does not
+// freeze the global proxy.
+
+var obj = this;
+obj = Object.freeze(obj);
diff --git a/test/mjsunit/regress/regress-1104.js b/test/mjsunit/regress/regress-1104.js
new file mode 100644
index 0000000..aca0a66
--- /dev/null
+++ b/test/mjsunit/regress/regress-1104.js
@@ -0,0 +1,37 @@
+// Copyright 2011 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.
+
+// A redeclaration of a variable that aliases a parameter and so rewrites to
+// an arguments object access should not record duplicate AST IDs for
+// bailout.
+function test(f) {
+ function f() {}
+ function f() {}
+ return arguments;
+}
+
+test();
diff --git a/test/mjsunit/regress/regress-1105.js b/test/mjsunit/regress/regress-1105.js
new file mode 100644
index 0000000..cfe2bd3
--- /dev/null
+++ b/test/mjsunit/regress/regress-1105.js
@@ -0,0 +1,38 @@
+// Copyright 2011 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.
+
+// This should properly catch the exception from the setter triggered
+// by the loaded file, and it should not fail an assertion in debug mode.
+
+__defineSetter__("x", function(){ throw 42; });
+
+try {
+ this.eval('function x(){}');
+ assertUnreachable();
+} catch (e) {
+ assertEquals(42, e);
+}
diff --git a/test/mjsunit/regress/regress-1107.js b/test/mjsunit/regress/regress-1107.js
new file mode 100644
index 0000000..4ba277a
--- /dev/null
+++ b/test/mjsunit/regress/regress-1107.js
@@ -0,0 +1,32 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that even if we cannot set element 0 on all the objects, we still
+// can format exception messages to some extent.
+
+Object.prototype.__defineGetter__(0, function(){});
+assertThrows("x");
diff --git a/test/mjsunit/regress/regress-1110.js b/test/mjsunit/regress/regress-1110.js
new file mode 100644
index 0000000..204a87b
--- /dev/null
+++ b/test/mjsunit/regress/regress-1110.js
@@ -0,0 +1,38 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that the illegal continue is thrown at parse time.
+
+try {
+ function Crash() { continue;if (Crash) {
+ } }
+ Crash();
+ assertTrue(false);
+} catch (e) {
+ assertTrue(e instanceof SyntaxError);
+ assertTrue(/continue/.test(e.message));
+}
diff --git a/test/mjsunit/regress/regress-1112.js b/test/mjsunit/regress/regress-1112.js
new file mode 100644
index 0000000..d780106
--- /dev/null
+++ b/test/mjsunit/regress/regress-1112.js
@@ -0,0 +1,36 @@
+// Copyright 2011 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.
+
+// Regression test making sure that defineProperty on the global proxy
+// defines the property on the global object.
+
+Object.defineProperty(this,
+ 1,
+ { configurable: true, enumerable: true, value: 3 });
+assertEquals(3, this[1]);
+assertTrue(this.hasOwnProperty("1"));
+
diff --git a/test/mjsunit/regress/regress-1117.js b/test/mjsunit/regress/regress-1117.js
new file mode 100644
index 0000000..b013a22
--- /dev/null
+++ b/test/mjsunit/regress/regress-1117.js
@@ -0,0 +1,35 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that we actually return the right value (-0) when we multiply
+// constant 0 with a negative integer.
+
+function foo(y) {return 0 * y; }
+for( var i = 0; i< 1000000; i++){
+ foo(42);
+}
+assertEquals(1/foo(-42), -Infinity);
diff --git a/test/mjsunit/regress/regress-1118.js b/test/mjsunit/regress/regress-1118.js
new file mode 100644
index 0000000..84f96e4
--- /dev/null
+++ b/test/mjsunit/regress/regress-1118.js
@@ -0,0 +1,50 @@
+// Copyright 2011 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.
+
+// An exception thrown in a function optimized by on-stack replacement (OSR)
+// should be able to construct a receiver from all optimized stack frames.
+
+function A() { }
+A.prototype.f = function() { }
+
+function B() { }
+
+var o = new A();
+
+// This function throws if o does not have an f property, and should not be
+// inlined.
+function g() { try { return o.f(); } finally { }}
+
+// This function should be optimized via OSR.
+function h() {
+ while(false) ;
+ for (var j = 0; j < 5000000; j++) g();
+}
+
+h();
+o = new B();
+assertThrows("h()");
diff --git a/test/mjsunit/regress/regress-1119.js b/test/mjsunit/regress/regress-1119.js
new file mode 100644
index 0000000..484893c
--- /dev/null
+++ b/test/mjsunit/regress/regress-1119.js
@@ -0,0 +1,45 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test runtime declaration of properties with var which are intercepted
+// by JS accessors.
+
+__proto__.__defineSetter__("x", function() { hasBeenInvoked = true; });
+__proto__.__defineSetter__("y", function() { throw 'exception'; });
+
+var hasBeenInvoked = false;
+eval("try { } catch (e) { var x = false; }");
+assertTrue(hasBeenInvoked);
+
+var exception;
+try {
+ eval("try { } catch (e) { var y = false; }");
+ assertUnreachable();
+} catch (e) {
+ exception = e;
+}
+assertEquals('exception', exception);
diff --git a/test/mjsunit/regress/regress-1120.js b/test/mjsunit/regress/regress-1120.js
new file mode 100644
index 0000000..c8c06aa
--- /dev/null
+++ b/test/mjsunit/regress/regress-1120.js
@@ -0,0 +1,33 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that retrieving the extensible value for the global object is
+// working correctly and does not return the bit from the global proxy map.
+
+var obj = this;
+Object.freeze(obj);
+assertFalse(Object.isExtensible(obj));
diff --git a/test/mjsunit/regress/regress-1121.js b/test/mjsunit/regress/regress-1121.js
new file mode 100644
index 0000000..0ad29cc
--- /dev/null
+++ b/test/mjsunit/regress/regress-1121.js
@@ -0,0 +1,34 @@
+// Copyright 2011 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.
+
+// See: http://code.google.com/p/v8/issues/detail?id=1121
+
+// Test that changing Array.prototype.__proto__ keeps Array functions working.
+
+Array.prototype.__proto__ = null;
+// pop has custom call generator, so we need some beefier function.
+assertEquals([1, 2, 3], [1, 2, 3].slice());
diff --git a/test/mjsunit/regress/regress-1122.js b/test/mjsunit/regress/regress-1122.js
new file mode 100644
index 0000000..7dc9b24
--- /dev/null
+++ b/test/mjsunit/regress/regress-1122.js
@@ -0,0 +1,55 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test that we can handle functions with up to 32766 arguments, and that
+// functions with more arguments throw an exception.
+
+// See http://code.google.com/p/v8/issues/detail?id=1122.
+
+function function_with_n_args(n) {
+ test_prefix = 'prefix ';
+ test_suffix = ' suffix';
+ var source = 'test_prefix + (function f(';
+ for (var arg = 0; arg < n ; arg++) {
+ if (arg != 0) source += ',';
+ source += 'arg' + arg;
+ }
+ source += ') { return arg' + (n - n % 2) / 2 + '; })(';
+ for (var arg = 0; arg < n ; arg++) {
+ if (arg != 0) source += ',';
+ source += arg;
+ }
+ source += ') + test_suffix';
+ return eval(source);
+}
+
+assertEquals('prefix 4000 suffix', function_with_n_args(8000));
+assertEquals('prefix 9000 suffix', function_with_n_args(18000));
+assertEquals('prefix 16000 suffix', function_with_n_args(32000));
+
+assertThrows("function_with_n_args(35000)");
+assertThrows("function_with_n_args(100000)");
diff --git a/test/mjsunit/regress/regress-1125.js b/test/mjsunit/regress/regress-1125.js
new file mode 100644
index 0000000..b0e1cb7
--- /dev/null
+++ b/test/mjsunit/regress/regress-1125.js
@@ -0,0 +1,41 @@
+// Copyright 2011 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Test a lot of updates to freshly created contexts.
+
+function f(x, y) {
+ with ("abcdefghijxxxxxxxxxx")
+ var y = {};
+}
+
+function g() {
+ f.apply(this, arguments);
+}
+
+for (var i = 0; i < 150000; i++) {
+ g(i);
+}
diff --git a/test/mjsunit/regress/regress-1126.js b/test/mjsunit/regress/regress-1126.js
new file mode 100644
index 0000000..303583b
--- /dev/null
+++ b/test/mjsunit/regress/regress-1126.js
@@ -0,0 +1,35 @@
+// Copyright 2011 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.
+
+// This should properly catch the exception from the setter triggered
+// by the loaded file, and it should not fail an assertion in debug mode.
+
+try {
+ eval('--');
+ assertUnreachable();
+} catch (e) {
+}