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..87fee33aaadee51ba3cae201207452ca2be57fa3 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,36 @@ void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
void LCodeGen::DoIsNull(LIsNull* instr) { |
- Abort("DoIsNull unimplemented."); |
+ Register reg = ToRegister(instr->input()); |
+ Register result = ToRegister(instr->result()); |
+ |
+ __ LoadRoot(ip, Heap::kNullValueRootIndex); |
+ __ cmp(reg, ip); |
+ if (instr->is_strict()) { |
+ __ LoadRoot(result, Heap::kTrueValueRootIndex, eq); |
+ __ LoadRoot(result, Heap::kFalseValueRootIndex, ne); |
+ } else { |
+ Label true_value, false_value, done; |
+ __ b(eq, &true_value); |
+ __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
+ __ cmp(ip, reg); |
+ __ 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)); |
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset)); |
+ __ tst(scratch, Operand(1 << Map::kIsUndetectable)); |
+ __ b(ne, &true_value); |
+ __ bind(&false_value); |
+ __ LoadRoot(result, Heap::kFalseValueRootIndex); |
+ __ jmp(&done); |
+ __ bind(&true_value); |
+ __ LoadRoot(result, Heap::kTrueValueRootIndex); |
+ __ bind(&done); |
+ } |
} |
@@ -1327,7 +1401,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 +1510,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 +1673,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 +1735,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 +1789,8 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
- Abort("DoBoundsCheck unimplemented."); |
+ __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
+ DeoptimizeIf(hs, instr->environment()); |
} |
@@ -2037,12 +2134,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) { |
- Abort("DoCheckPrototypeMaps unimplemented."); |
+ Register temp1 = ToRegister(instr->temp1()); |
+ Register temp2 = 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(temp1, current_prototype); |
+ |
+ // Check prototype maps up to the holder. |
+ while (!current_prototype.is_identical_to(holder)) { |
+ __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); |
+ __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); |
+ DeoptimizeIf(ne, instr->environment()); |
+ current_prototype = |
+ Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
+ // Load next prototype object. |
+ LoadPrototype(temp1, current_prototype); |
+ } |
+ |
+ // Check the holder map. |
+ __ ldr(temp2, FieldMemOperand(temp1, HeapObject::kMapOffset)); |
+ __ cmp(temp2, Operand(Handle<Map>(current_prototype->map()))); |
+ DeoptimizeIf(ne, instr->environment()); |
} |