Use a separate marker value to allocate the arguments object on deoptimzation.

Before we used the hole value for this purpose, but this does not work once we
start using the hole value for other purposes in the optimizing compiler.

Review URL: http://codereview.chromium.org/6116001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6210 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2011-01-06 15:53:56 +00:00
parent d4bbad8e4e
commit 5fbaece14c
14 changed files with 55 additions and 28 deletions

View File

@ -775,7 +775,7 @@ MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
if (index >= 0) {
Handle<Object> arguments =
Handle<Object>(frame->GetExpression(index));
if (!arguments->IsTheHole()) return *arguments;
if (!arguments->IsArgumentsMarker()) return *arguments;
}
// If there isn't an arguments variable in the stack, we need to

View File

@ -596,7 +596,7 @@ void CodeGenerator::StoreArgumentsObject(bool initial) {
// When using lazy arguments allocation, we store the hole value
// as a sentinel indicating that the arguments object hasn't been
// allocated yet.
frame_->EmitPushRoot(Heap::kTheHoleValueRootIndex);
frame_->EmitPushRoot(Heap::kArgumentsMarkerRootIndex);
} else {
frame_->SpillAll();
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
@ -623,7 +623,7 @@ void CodeGenerator::StoreArgumentsObject(bool initial) {
// has a local variable named 'arguments'.
LoadFromSlot(scope()->arguments()->AsSlot(), NOT_INSIDE_TYPEOF);
Register arguments = frame_->PopToRegister();
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ LoadRoot(ip, Heap::kArgumentsMarkerRootIndex);
__ cmp(arguments, ip);
done.Branch(ne);
}
@ -1748,7 +1748,7 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
// named 'arguments' has been introduced.
JumpTarget slow;
Label done;
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ LoadRoot(ip, Heap::kArgumentsMarkerRootIndex);
__ cmp(ip, arguments_reg);
slow.Branch(ne);
@ -3255,7 +3255,7 @@ void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
// If the loaded value is the sentinel that indicates that we
// haven't loaded the arguments object yet, we need to do it now.
JumpTarget exit;
__ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
__ LoadRoot(ip, Heap::kArgumentsMarkerRootIndex);
__ cmp(tos, ip);
exit.Branch(ne);
frame_->Drop();

View File

@ -647,6 +647,11 @@ ExternalReference ExternalReference::the_hole_value_location() {
}
ExternalReference ExternalReference::arguments_marker_location() {
return ExternalReference(Factory::arguments_marker().location());
}
ExternalReference ExternalReference::roots_address() {
return ExternalReference(Heap::roots_address());
}

View File

@ -512,6 +512,9 @@ class ExternalReference BASE_EMBEDDED {
// Static variable Factory::the_hole_value.location()
static ExternalReference the_hole_value_location();
// Static variable Factory::arguments_marker.location()
static ExternalReference arguments_marker_location();
// Static variable Heap::roots_address()
static ExternalReference roots_address();

View File

@ -618,17 +618,17 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
}
case Translation::ARGUMENTS_OBJECT: {
// Use the hole value as a sentinel and fill in the arguments object
// after the deoptimized frame is built.
// Use the arguments marker value as a sentinel and fill in the arguments
// object after the deoptimized frame is built.
ASSERT(frame_index == 0); // Only supported for first frame.
if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ",
output_[frame_index]->GetTop() + output_offset,
output_offset);
Heap::the_hole_value()->ShortPrint();
Heap::arguments_marker()->ShortPrint();
PrintF(" ; arguments object\n");
}
intptr_t value = reinterpret_cast<intptr_t>(Heap::the_hole_value());
intptr_t value = reinterpret_cast<intptr_t>(Heap::arguments_marker());
output_[frame_index]->SetFrameSlot(output_offset, value);
return;
}

View File

@ -2011,6 +2011,12 @@ bool Heap::CreateInitialObjects() {
}
set_the_hole_value(obj);
{ MaybeObject* maybe_obj = CreateOddball("arguments_marker",
Smi::FromInt(-4));
if (!maybe_obj->ToObject(&obj)) return false;
}
set_arguments_marker(obj);
{ MaybeObject* maybe_obj =
CreateOddball("no_interceptor_result_sentinel", Smi::FromInt(-2));
if (!maybe_obj->ToObject(&obj)) return false;

View File

@ -53,6 +53,7 @@ namespace internal {
V(Object, null_value, NullValue) \
V(Object, true_value, TrueValue) \
V(Object, false_value, FalseValue) \
V(Object, arguments_marker, ArgumentsMarker) \
V(Map, heap_number_map, HeapNumberMap) \
V(Map, global_context_map, GlobalContextMap) \
V(Map, fixed_array_map, FixedArrayMap) \

View File

@ -745,10 +745,10 @@ Result CodeGenerator::StoreArgumentsObject(bool initial) {
Comment cmnt(masm_, "[ store arguments object");
if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) {
// When using lazy arguments allocation, we store the hole value
// When using lazy arguments allocation, we store the arguments marker value
// as a sentinel indicating that the arguments object hasn't been
// allocated yet.
frame_->Push(Factory::the_hole_value());
frame_->Push(Factory::arguments_marker());
} else {
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
frame_->PushFunction();
@ -773,9 +773,9 @@ Result CodeGenerator::StoreArgumentsObject(bool initial) {
if (probe.is_constant()) {
// We have to skip updating the arguments object if it has
// been assigned a proper value.
skip_arguments = !probe.handle()->IsTheHole();
skip_arguments = !probe.handle()->IsArgumentsMarker();
} else {
__ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value()));
__ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
probe.Unuse();
done.Branch(not_equal);
}
@ -3294,9 +3294,9 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
Label slow, done;
bool try_lazy = true;
if (probe.is_constant()) {
try_lazy = probe.handle()->IsTheHole();
try_lazy = probe.handle()->IsArgumentsMarker();
} else {
__ cmp(Operand(probe.reg()), Immediate(Factory::the_hole_value()));
__ cmp(Operand(probe.reg()), Immediate(Factory::arguments_marker()));
probe.Unuse();
__ j(not_equal, &slow);
}
@ -5068,7 +5068,7 @@ void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
// object has been lazily loaded yet.
Result result = frame()->Pop();
if (result.is_constant()) {
if (result.handle()->IsTheHole()) {
if (result.handle()->IsArgumentsMarker()) {
result = StoreArgumentsObject(false);
}
frame()->Push(&result);
@ -5079,7 +5079,7 @@ void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
// indicates that we haven't loaded the arguments object yet, we
// need to do it now.
JumpTarget exit;
__ cmp(Operand(result.reg()), Immediate(Factory::the_hole_value()));
__ cmp(Operand(result.reg()), Immediate(Factory::arguments_marker()));
frame()->Push(&result);
exit.Branch(not_equal);

View File

@ -368,8 +368,10 @@ void Oddball::OddballVerify() {
} else {
ASSERT(number->IsSmi());
int value = Smi::cast(number)->value();
ASSERT(value == 0 || value == 1 || value == -1 ||
value == -2 || value == -3);
// Hidden oddballs have negative smis.
const int kLeastHiddenOddballNumber = -4;
ASSERT(value <= 1);
ASSERT(value >= kLeastHiddenOddballNumber);
}
}

View File

@ -423,6 +423,11 @@ bool MaybeObject::IsTheHole() {
}
bool MaybeObject::IsArgumentsMarker() {
return this == Heap::arguments_marker();
}
Failure* Failure::cast(MaybeObject* obj) {
ASSERT(HAS_FAILURE_TAG(obj));
return reinterpret_cast<Failure*>(obj);

View File

@ -593,6 +593,7 @@ class MaybeObject BASE_EMBEDDED {
inline bool IsOutOfMemory();
inline bool IsException();
INLINE(bool IsTheHole());
INLINE(bool IsArgumentsMarker());
inline bool ToObject(Object** obj) {
if (IsFailure()) return false;
*obj = reinterpret_cast<Object*>(this);

View File

@ -6748,7 +6748,7 @@ static MaybeObject* Runtime_NotifyDeoptimized(Arguments args) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<Object> arguments;
for (int i = frame->ComputeExpressionsCount() - 1; i >= 0; --i) {
if (frame->GetExpression(i) == Heap::the_hole_value()) {
if (frame->GetExpression(i) == Heap::arguments_marker()) {
if (arguments.is_null()) {
// FunctionGetArguments can't throw an exception, so cast away the
// doubt with an assert.

View File

@ -498,6 +498,10 @@ void ExternalReferenceTable::PopulateTable() {
UNCLASSIFIED,
39,
"power_double_int_function");
Add(ExternalReference::arguments_marker_location().address(),
UNCLASSIFIED,
40,
"Factory::arguments_marker().location()");
}

View File

@ -627,10 +627,10 @@ Result CodeGenerator::StoreArgumentsObject(bool initial) {
Comment cmnt(masm_, "[ store arguments object");
if (mode == LAZY_ARGUMENTS_ALLOCATION && initial) {
// When using lazy arguments allocation, we store the hole value
// When using lazy arguments allocation, we store the arguments marker value
// as a sentinel indicating that the arguments object hasn't been
// allocated yet.
frame_->Push(Factory::the_hole_value());
frame_->Push(Factory::arguments_marker());
} else {
ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
frame_->PushFunction();
@ -655,9 +655,9 @@ Result CodeGenerator::StoreArgumentsObject(bool initial) {
if (probe.is_constant()) {
// We have to skip updating the arguments object if it has
// been assigned a proper value.
skip_arguments = !probe.handle()->IsTheHole();
skip_arguments = !probe.handle()->IsArgumentsMarker();
} else {
__ CompareRoot(probe.reg(), Heap::kTheHoleValueRootIndex);
__ CompareRoot(probe.reg(), Heap::kArgumentsMarkerRootIndex);
probe.Unuse();
done.Branch(not_equal);
}
@ -2516,9 +2516,9 @@ void CodeGenerator::CallApplyLazy(Expression* applicand,
Label slow, done;
bool try_lazy = true;
if (probe.is_constant()) {
try_lazy = probe.handle()->IsTheHole();
try_lazy = probe.handle()->IsArgumentsMarker();
} else {
__ CompareRoot(probe.reg(), Heap::kTheHoleValueRootIndex);
__ CompareRoot(probe.reg(), Heap::kArgumentsMarkerRootIndex);
probe.Unuse();
__ j(not_equal, &slow);
}
@ -4417,7 +4417,7 @@ void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
// If the loaded value is a constant, we know if the arguments
// object has been lazily loaded yet.
if (value.is_constant()) {
if (value.handle()->IsTheHole()) {
if (value.handle()->IsArgumentsMarker()) {
Result arguments = StoreArgumentsObject(false);
frame_->Push(&arguments);
} else {
@ -4430,7 +4430,7 @@ void CodeGenerator::LoadFromSlotCheckForArguments(Slot* slot,
// indicates that we haven't loaded the arguments object yet, we
// need to do it now.
JumpTarget exit;
__ CompareRoot(value.reg(), Heap::kTheHoleValueRootIndex);
__ CompareRoot(value.reg(), Heap::kArgumentsMarkerRootIndex);
frame_->Push(&value);
exit.Branch(not_equal);
Result arguments = StoreArgumentsObject(false);