Commit 99503281 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

MIPS: port Merge arguments branch to bleeding edge (second try).

Ported r8315 (d70d395).

BUG=
TEST=

Review URL: http://codereview.chromium.org//7216004
Patch from Paul Lind <plind44@gmail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8340 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 57c1899f
This diff is collapsed.
......@@ -238,17 +238,17 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
// function, receiver address, parameter count.
// The stub will rewrite receiever and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub stub(
is_strict_mode() ? ArgumentsAccessStub::NEW_STRICT
: ArgumentsAccessStub::NEW_NON_STRICT);
ArgumentsAccessStub::Type type;
if (is_strict_mode()) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (function()->has_duplicate_parameters()) {
type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
} else {
type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
}
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
Variable* arguments_shadow = scope()->arguments_shadow();
if (arguments_shadow != NULL) {
// Duplicate the value; move-to-slot operation might clobber registers.
__ mov(a3, v0);
Move(arguments_shadow->AsSlot(), a3, a1, a2);
}
Move(arguments->AsSlot(), v0, a1, a2);
}
......@@ -1254,13 +1254,12 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
void FullCodeGenerator::EmitVariableLoad(Variable* var) {
// Four cases: non-this global variables, lookup slots, all other
// types of slots, and parameters that rewrite to explicit property
// accesses on the arguments object.
// Three cases: non-this global variables, lookup slots, and all other
// types of slots.
Slot* slot = var->AsSlot();
Property* property = var->AsProperty();
ASSERT((var->is_global() && !var->is_this()) == (slot == NULL));
if (var->is_global() && !var->is_this()) {
if (slot == NULL) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in a2 and the global
// object (receiver) in a0.
......@@ -1270,7 +1269,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT, AstNode::kNoNumber);
context()->Plug(v0);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
} else if (slot->type() == Slot::LOOKUP) {
Label done, slow;
// Generate code for loading from variables potentially shadowed
......@@ -1286,7 +1285,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
context()->Plug(v0);
} else if (slot != NULL) {
} else {
Comment cmnt(masm_, (slot->type() == Slot::CONTEXT)
? "Context slot"
: "Stack slot");
......@@ -1303,31 +1302,6 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
} else {
context()->Plug(slot);
}
} else {
Comment cmnt(masm_, "Rewritten parameter");
ASSERT_NOT_NULL(property);
// Rewritten parameter accesses are of the form "slot[literal]".
// Assert that the object is in a slot.
Variable* object_var = property->obj()->AsVariableProxy()->AsVariable();
ASSERT_NOT_NULL(object_var);
Slot* object_slot = object_var->AsSlot();
ASSERT_NOT_NULL(object_slot);
// Load the object.
Move(a1, object_slot);
// Assert that the key is a smi.
Literal* key_literal = property->key()->AsLiteral();
ASSERT_NOT_NULL(key_literal);
ASSERT(key_literal->handle()->IsSmi());
// Load the key.
__ li(a0, Operand(key_literal->handle()));
// Call keyed load IC. It has arguments key and receiver in a0 and a1.
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
context()->Plug(v0);
}
}
......@@ -1571,7 +1545,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
// Left-hand side can only be a property, a global or a (parameter or local)
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
LhsKind assign_type = VARIABLE;
Property* property = expr->target()->AsProperty();
......@@ -1598,27 +1572,13 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case KEYED_PROPERTY:
// We need the key and receiver on both the stack and in v0 and a1.
if (expr->is_compound()) {
if (property->is_arguments_access()) {
VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
__ lw(v0, EmitSlotSearch(obj_proxy->var()->AsSlot(), v0));
__ push(v0);
__ li(v0, Operand(property->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(property->obj());
VisitForAccumulatorValue(property->key());
}
VisitForStackValue(property->obj());
VisitForAccumulatorValue(property->key());
__ lw(a1, MemOperand(sp, 0));
__ push(v0);
} else {
if (property->is_arguments_access()) {
VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
__ lw(a1, EmitSlotSearch(obj_proxy->var()->AsSlot(), v0));
__ li(v0, Operand(property->key()->AsLiteral()->handle()));
__ Push(a1, v0);
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
}
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
}
break;
}
......@@ -1828,7 +1788,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
}
// Left-hand side can only be a property, a global or a (parameter or local)
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
LhsKind assign_type = VARIABLE;
Property* prop = expr->AsProperty();
......@@ -1859,20 +1819,10 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
}
case KEYED_PROPERTY: {
__ push(result_register()); // Preserve value.
if (prop->is_synthetic()) {
ASSERT(prop->obj()->AsVariableProxy() != NULL);
ASSERT(prop->key()->AsLiteral() != NULL);
{ AccumulatorValueContext for_object(this);
EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
}
__ mov(a2, result_register());
__ li(a1, Operand(prop->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
__ mov(a1, result_register());
__ pop(a2);
}
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
__ mov(a1, result_register());
__ pop(a2);
__ pop(a0); // Restore value.
Handle<Code> ic = is_strict_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
......@@ -1888,8 +1838,6 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
// Left-hand sides that rewrite to explicit property accesses do not reach
// here.
ASSERT(var != NULL);
ASSERT(var->is_global() || var->AsSlot() != NULL);
......@@ -3840,7 +3788,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
// Expression can only be a property, a global or a (parameter or local)
// slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
// slot.
enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
LhsKind assign_type = VARIABLE;
Property* prop = expr->expression()->AsProperty();
......@@ -3868,15 +3816,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ push(v0);
EmitNamedPropertyLoad(prop);
} else {
if (prop->is_arguments_access()) {
VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
__ lw(v0, EmitSlotSearch(obj_proxy->var()->AsSlot(), v0));
__ push(v0);
__ li(v0, Operand(prop->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
}
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
__ lw(a1, MemOperand(sp, 0));
__ push(v0);
EmitKeyedPropertyLoad(prop);
......
......@@ -893,6 +893,160 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
}
static MemOperand GenerateMappedArgumentsLookup(MacroAssembler* masm,
Register object,
Register key,
Register scratch1,
Register scratch2,
Register scratch3,
Label* unmapped_case,
Label* slow_case) {
Heap* heap = masm->isolate()->heap();
// Check that the receiver isn't a smi.
__ JumpIfSmi(object, slow_case);
// Check that the key is a positive smi.
__ And(scratch1, scratch1, Operand(0x8000001));
__ Branch(slow_case, ne, key, Operand(scratch1));
// Load the elements into scratch1 and check its map.
Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
__ lw(scratch1, FieldMemOperand(object, JSObject::kElementsOffset));
__ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK);
// Check if element is in the range of mapped arguments. If not, jump
// to the unmapped lookup with the parameter map in scratch1.
__ lw(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset));
__ Subu(scratch2, scratch2, Operand(Smi::FromInt(2)));
__ Branch(unmapped_case, Ugreater_equal, key, Operand(scratch2));
// Load element index and check whether it is the hole.
const int kOffset =
FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag;
__ li(scratch3, Operand(kPointerSize >> 1));
__ mul(scratch3, key, scratch3);
__ Addu(scratch3, scratch3, Operand(kOffset));
__ Addu(scratch2, scratch1, scratch3);
__ lw(scratch2, MemOperand(scratch2));
__ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex);
__ Branch(unmapped_case, eq, scratch2, Operand(scratch3));
// Load value from context and return it. We can reuse scratch1 because
// we do not jump to the unmapped lookup (which requires the parameter
// map in scratch1).
__ lw(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
__ li(scratch3, Operand(kPointerSize >> 1));
__ mul(scratch3, scratch2, scratch3);
__ Addu(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag));
__ Addu(scratch2, scratch1, scratch3);
return MemOperand(scratch2);
}
static MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
Register key,
Register parameter_map,
Register scratch,
Label* slow_case) {
// Element is in arguments backing store, which is referenced by the
// second element of the parameter_map. The parameter_map register
// must be loaded with the parameter map of the arguments object and is
// overwritten.
const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
Register backing_store = parameter_map;
__ lw(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset));
__ lw(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset));
__ Branch(slow_case, Ugreater_equal, key, Operand(scratch));
__ li(scratch, Operand(kPointerSize >> 1));
__ mul(scratch, key, scratch);
__ Addu(scratch,
scratch,
Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ Addu(scratch, backing_store, scratch);
return MemOperand(scratch);
}
void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- lr : return address
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
Label slow, notin;
MemOperand mapped_location =
GenerateMappedArgumentsLookup(masm, a1, v0, a2, a3, t0, &notin, &slow);
__ lw(v0, mapped_location);
__ Ret();
__ bind(&notin);
// The unmapped lookup expects that the parameter map is in a2.
MemOperand unmapped_location =
GenerateUnmappedArgumentsLookup(masm, v0, a2, a3, &slow);
__ lw(a2, unmapped_location);
__ Branch(&slow, eq, a2, Operand(a3));
__ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
__ mov(v0, a2);
__ Ret();
__ bind(&slow);
GenerateMiss(masm, false);
}
void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- v0 : value
// -- a1 : key
// -- a2 : receiver
// -- lr : return address
// -----------------------------------
Label slow, notin;
MemOperand mapped_location =
GenerateMappedArgumentsLookup(masm, a2, a1, a3, t0, t1, &notin, &slow);
__ sw(v0, mapped_location);
__ Ret();
__ bind(&notin);
// The unmapped lookup expects that the parameter map is in a3.
MemOperand unmapped_location =
GenerateUnmappedArgumentsLookup(masm, a1, a3, t0, &slow);
__ sw(v0, unmapped_location);
__ Ret();
__ bind(&slow);
GenerateMiss(masm, false);
}
void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm,
int argc) {
// ----------- S t a t e -------------
// -- a2 : name
// -- lr : return address
// -----------------------------------
Label slow, notin;
// Load receiver.
__ lw(a1, MemOperand(sp, argc * kPointerSize));
MemOperand mapped_location =
GenerateMappedArgumentsLookup(masm, a1, a2, a3, t0, t1, &notin, &slow);
__ lw(a1, mapped_location);
GenerateFunctionTailCall(masm, argc, &slow, a3);
__ bind(&notin);
// The unmapped lookup expects that the parameter map is in a3.
MemOperand unmapped_location =
GenerateUnmappedArgumentsLookup(masm, a2, a3, t0, &slow);
__ lw(a1, unmapped_location);
__ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
__ Branch(&slow, eq, a1, Operand(a3));
GenerateFunctionTailCall(masm, argc, &slow, a3);
__ bind(&slow);
GenerateMiss(masm, argc);
}
Object* KeyedLoadIC_Miss(Arguments args);
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm, bool force_generic) {
// ---------- S t a t e --------------
// -- ra : return address
......
......@@ -3408,6 +3408,7 @@ static bool IsElementTypeSigned(JSObject::ElementsKind elements_kind) {
case JSObject::FAST_ELEMENTS:
case JSObject::FAST_DOUBLE_ELEMENTS:
case JSObject::DICTIONARY_ELEMENTS:
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
return false;
}
......@@ -3502,6 +3503,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
case JSObject::FAST_ELEMENTS:
case JSObject::FAST_DOUBLE_ELEMENTS:
case JSObject::DICTIONARY_ELEMENTS:
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
......@@ -3861,6 +3863,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
case JSObject::FAST_ELEMENTS:
case JSObject::FAST_DOUBLE_ELEMENTS:
case JSObject::DICTIONARY_ELEMENTS:
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
......@@ -3926,6 +3929,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
case JSObject::FAST_ELEMENTS:
case JSObject::FAST_DOUBLE_ELEMENTS:
case JSObject::DICTIONARY_ELEMENTS:
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
......@@ -4095,6 +4099,7 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
case JSObject::FAST_ELEMENTS:
case JSObject::FAST_DOUBLE_ELEMENTS:
case JSObject::DICTIONARY_ELEMENTS:
case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment