First part of lithium ARM port.
authorkarlklose@chromium.org <karlklose@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 4 Jan 2011 13:02:51 +0000 (13:02 +0000)
committerkarlklose@chromium.org <karlklose@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 4 Jan 2011 13:02:51 +0000 (13:02 +0000)
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

src/arm/lithium-arm.cc
src/arm/lithium-arm.h
src/arm/lithium-codegen-arm.cc
src/hydrogen-instructions.h

index 6c82f3d..4db93b7 100644 (file)
@@ -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);
index 5b152ef..b37c2ee 100644 (file)
@@ -1121,27 +1121,25 @@ class LBranch: public LUnaryOperation {
 
 class LCmpMapAndBranch: public LUnaryOperation {
  public:
-  LCmpMapAndBranch(LOperand* value,
-                   Handle<Map> 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> 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> 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> 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<JSObject> holder,
                       Handle<Map> 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<JSObject> holder() const { return holder_; }
   Handle<Map> receiver_map() const { return receiver_map_; }
 
  private:
-  LOperand* temp_;
+  LOperand* temp1_;
+  LOperand* temp2_;
   Handle<JSObject> holder_;
   Handle<Map> receiver_map_;
 };
index 53a4325..87fee33 100644 (file)
@@ -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());
 }
 
 
index 3a4f2f7..a3c23c6 100644 (file)
@@ -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> map() const { return map_; }