Chromium Code Reviews| Index: src/arm/lithium-codegen-arm.cc |
| diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc |
| index 53a4325c5e80a53077f1fa562d835f12e7fae112..b5f5338a13c5372f1261139c4ca7ae8e04a20fcf 100644 |
| --- a/src/arm/lithium-codegen-arm.cc |
| +++ b/src/arm/lithium-codegen-arm.cc |
| @@ -730,7 +730,53 @@ void LCodeGen::DoParameter(LParameter* instr) { |
| void LCodeGen::DoCallStub(LCallStub* instr) { |
| - Abort("DoCallStub unimplemented."); |
| + ASSERT(ToRegister(instr->result()).is(r0)); |
| + 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: { |
| + Abort("StringCharAtStub unimplemented."); |
| + break; |
| + } |
| + case CodeStub::MathPow: { |
| + Abort("MathPowStub unimplemented."); |
| + 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: { |
| + Abort("TranscendentalCache unimplemented."); |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + } |
| } |
| @@ -902,7 +948,6 @@ void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| Register result = ToRegister(instr->result()); |
| Register array = ToRegister(instr->input()); |
| __ ldr(result, FieldMemOperand(array, JSArray::kLengthOffset)); |
| - Abort("DoJSArrayLength untested."); |
| } |
| @@ -1171,7 +1216,38 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| void LCodeGen::DoIsNull(LIsNull* instr) { |
| - Abort("DoIsNull unimplemented."); |
| + Register reg = ToRegister(instr->input()); |
| + Register result = ToRegister(instr->result()); |
| + |
| + __ cmp(reg, Operand(Factory::null_value())); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
ou should use the root array for reading these fix
Karl Klose
2011/01/04 12:32:18
Done.
|
| + if (instr->is_strict()) { |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Two conditional LoadRoot should work here.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + __ mov(result, Operand(Handle<Object>(Heap::true_value()))); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Use root array.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + Label done; |
| + __ b(eq, &done); |
| + __ mov(result, Operand(Handle<Object>(Heap::false_value()))); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Use root array.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + __ bind(&done); |
| + } else { |
| + Label true_value, false_value, done; |
| + __ b(eq, &true_value); |
| + __ cmp(reg, Operand(Factory::undefined_value())); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Use root array.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + __ b(eq, &true_value); |
| + __ tst(reg, Operand(kSmiTagMask)); |
| + __ b(eq, &false_value); |
| + // Check for undetectable objects by looking in the bit field in |
| + // the map. The object has already been smi checked. |
| + Register scratch = result; |
| + __ ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset)); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Code in comment.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + //__ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| + __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
| + __ tst(scratch, Operand(1 << Map::kIsUndetectable)); |
| + __ b(ne, &true_value); |
| + __ bind(&false_value); |
| + __ mov(result, Operand(Handle<Object>(Heap::false_value()))); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Use root array.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + __ jmp(&done); |
| + __ bind(&true_value); |
| + __ mov(result, Operand(Handle<Object>(Heap::true_value()))); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
Use root array.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + __ bind(&done); |
| + } |
| } |
| @@ -1327,7 +1403,14 @@ void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| - Abort("DoCmpMapAndBranch unimplemented."); |
| + Register reg = ToRegister(instr->input()); |
| + Register temp = ToRegister(instr->temp()); |
| + int true_block = instr->true_block_id(); |
| + int false_block = instr->false_block_id(); |
| + |
| + __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| + __ cmp(temp, Operand(instr->map())); |
| + EmitBranch(true_block, false_block, eq); |
| } |
| @@ -1429,7 +1512,14 @@ void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
| void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| - Abort("DoLoadNamedField unimplemented."); |
| + Register object = ToRegister(instr->input()); |
| + Register result = ToRegister(instr->result()); |
| + if (instr->hydrogen()->is_in_object()) { |
| + __ ldr(result, FieldMemOperand(object, instr->hydrogen()->offset())); |
| + } else { |
| + __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); |
| + __ ldr(result, FieldMemOperand(result, instr->hydrogen()->offset())); |
| + } |
| } |
| @@ -1585,7 +1675,9 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| - Abort("DoCallConstantFunction unimplemented."); |
| + ASSERT(ToRegister(instr->result()).is(r0)); |
| + __ mov(r1, Operand(instr->function())); |
| + CallKnownFunction(instr->function(), instr->arity(), instr); |
| } |
| @@ -1645,7 +1737,13 @@ void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| - Abort("DoCallFunction unimplemented."); |
| + ASSERT(ToRegister(instr->result()).is(r0)); |
| + |
| + int arity = instr->arity(); |
| + CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
| + CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| + __ Drop(1); |
| + __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| } |
| @@ -1693,7 +1791,8 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| - Abort("DoBoundsCheck unimplemented."); |
| + __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
To much indention.
Karl Klose
2011/01/04 12:32:18
Done.
|
| + DeoptimizeIf(hs, instr->environment()); |
| } |
| @@ -2037,12 +2136,42 @@ void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| void LCodeGen::LoadPrototype(Register result, |
| Handle<JSObject> prototype) { |
| - Abort("LoadPrototype unimplemented."); |
| + if (Heap::InNewSpace(*prototype)) { |
| + Handle<JSGlobalPropertyCell> cell = |
| + Factory::NewJSGlobalPropertyCell(prototype); |
| + __ mov(result, Operand(cell)); |
| + } else { |
| + __ mov(result, Operand(prototype)); |
| + } |
| } |
| void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
|
Søren Thygesen Gjesse
2011/01/04 11:23:34
reg -> temp1, temp -> temp2?
Karl Klose
2011/01/04 12:32:18
Done.
|
| - Abort("DoCheckPrototypeMaps unimplemented."); |
| + Register reg = ToRegister(instr->temp1()); |
| + Register temp = ToRegister(instr->temp2()); |
| + |
| + Handle<JSObject> holder = instr->holder(); |
| + Handle<Map> receiver_map = instr->receiver_map(); |
| + Handle<JSObject> current_prototype(JSObject::cast(receiver_map->prototype())); |
| + |
| + // Load prototype object. |
| + LoadPrototype(reg, current_prototype); |
| + |
| + // Check prototype maps up to the holder. |
| + while (!current_prototype.is_identical_to(holder)) { |
| + __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| + __ cmp(temp, Operand(Handle<Map>(current_prototype->map()))); |
| + DeoptimizeIf(ne, instr->environment()); |
| + current_prototype = |
| + Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
| + // Load next prototype object. |
| + LoadPrototype(reg, current_prototype); |
| + } |
| + |
| + // Check the holder map. |
| + __ ldr(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| + __ cmp(temp, Operand(Handle<Map>(current_prototype->map()))); |
| + DeoptimizeIf(ne, instr->environment()); |
| } |