From: karlklose@chromium.org Date: Tue, 4 Jan 2011 13:02:51 +0000 (+0000) Subject: First part of lithium ARM port. X-Git-Tag: upstream/4.7.83~20699 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=20c858d5149ca165d1723e49170e1bdcfd5af13b;p=platform%2Fupstream%2Fv8.git First part of lithium ARM port. Implement LoadNamedField, CallConstantFunction, CmpMapAndBranch, JSArrayLength, BoundsCheck, IsNull, CallFunction, and CallStub in the ARM lithium codegenerator. BUG= TEST= Review URL: http://codereview.chromium.org/6069010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6155 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 6c82f3d..4db93b7 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1292,12 +1292,8 @@ LInstruction* LChunkBuilder::DoCompareMapAndBranch( HCompareMapAndBranch* instr) { ASSERT(instr->value()->representation().IsTagged()); LOperand* value = UseRegisterAtStart(instr->value()); - HBasicBlock* first = instr->FirstSuccessor(); - HBasicBlock* second = instr->SecondSuccessor(); - return new LCmpMapAndBranch(value, - instr->map(), - first->block_id(), - second->block_id()); + LOperand* temp = TempRegister(); + return new LCmpMapAndBranch(value, temp); } @@ -1367,6 +1363,9 @@ LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { return AssignEnvironment(DefineAsRegister(result)); case kMathSqrt: return DefineSameAsFirst(result); + case kMathRound: + Abort("MathRound LUnaryMathOperation not implemented"); + return NULL; case kMathPowHalf: Abort("MathPowHalf LUnaryMathOperation not implemented"); return NULL; @@ -1771,9 +1770,11 @@ LInstruction* LChunkBuilder::DoCheckInstanceType(HCheckInstanceType* instr) { LInstruction* LChunkBuilder::DoCheckPrototypeMaps(HCheckPrototypeMaps* instr) { - LOperand* temp = TempRegister(); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = TempRegister(); LInstruction* result = - new LCheckPrototypeMaps(temp, + new LCheckPrototypeMaps(temp1, + temp2, instr->holder(), instr->receiver_map()); return AssignEnvironment(result); diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index 5b152ef..b37c2ee 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -1121,27 +1121,25 @@ class LBranch: public LUnaryOperation { class LCmpMapAndBranch: public LUnaryOperation { public: - LCmpMapAndBranch(LOperand* value, - Handle map, - int true_block_id, - int false_block_id) - : LUnaryOperation(value), - map_(map), - true_block_id_(true_block_id), - false_block_id_(false_block_id) { } + LCmpMapAndBranch(LOperand* value, LOperand* temp) + : LUnaryOperation(value), temp_(temp) { } DECLARE_CONCRETE_INSTRUCTION(CmpMapAndBranch, "cmp-map-and-branch") + DECLARE_HYDROGEN_ACCESSOR(CompareMapAndBranch) virtual bool IsControl() const { return true; } - Handle map() const { return map_; } - int true_block_id() const { return true_block_id_; } - int false_block_id() const { return false_block_id_; } + LOperand* temp() const { return temp_; } + Handle map() const { return hydrogen()->map(); } + int true_block_id() const { + return hydrogen()->true_destination()->block_id(); + } + int false_block_id() const { + return hydrogen()->false_destination()->block_id(); + } private: - Handle map_; - int true_block_id_; - int false_block_id_; + LOperand* temp_; }; @@ -1678,21 +1676,25 @@ class LCheckMap: public LUnaryOperation { class LCheckPrototypeMaps: public LInstruction { public: - LCheckPrototypeMaps(LOperand* temp, + LCheckPrototypeMaps(LOperand* temp1, + LOperand* temp2, Handle holder, Handle receiver_map) - : temp_(temp), + : temp1_(temp1), + temp2_(temp2), holder_(holder), receiver_map_(receiver_map) { } DECLARE_CONCRETE_INSTRUCTION(CheckPrototypeMaps, "check-prototype-maps") - LOperand* temp() const { return temp_; } + LOperand* temp1() const { return temp1_; } + LOperand* temp2() const { return temp2_; } Handle holder() const { return holder_; } Handle receiver_map() const { return receiver_map_; } private: - LOperand* temp_; + LOperand* temp1_; + LOperand* temp2_; Handle holder_; Handle receiver_map_; }; diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 53a4325..87fee33 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 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 prototype) { - Abort("LoadPrototype unimplemented."); + if (Heap::InNewSpace(*prototype)) { + Handle 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 holder = instr->holder(); + Handle receiver_map = instr->receiver_map(); + Handle 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(current_prototype->map()))); + DeoptimizeIf(ne, instr->environment()); + current_prototype = + Handle(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(current_prototype->map()))); + DeoptimizeIf(ne, instr->environment()); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 3a4f2f7..a3c23c6 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -910,6 +910,9 @@ class HCompareMapAndBranch: public HUnaryControlInstruction { virtual HBasicBlock* FirstSuccessor() const { return true_destination_; } virtual HBasicBlock* SecondSuccessor() const { return false_destination_; } + HBasicBlock* true_destination() const { return true_destination_; } + HBasicBlock* false_destination() const { return false_destination_; } + virtual void PrintDataTo(StringStream* stream) const; Handle map() const { return map_; }