Revision: 6271
Author: [email protected]
Date: Tue Jan 11 06:01:53 2011
Log: ARM: Implement ClassOf in the lithium arm backend.
Review URL: http://codereview.chromium.org/6201004
http://code.google.com/p/v8/source/detail?r=6271
Modified:
/branches/bleeding_edge/src/arm/lithium-arm.cc
/branches/bleeding_edge/src/arm/lithium-arm.h
/branches/bleeding_edge/src/arm/lithium-codegen-arm.cc
/branches/bleeding_edge/src/ia32/lithium-ia32.h
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Jan 11 04:10:11 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc Tue Jan 11 06:01:53 2011
@@ -998,7 +998,6 @@
return new LClassOfTestAndBranch(UseTempRegister(compare->value()),
TempRegister(),
- TempRegister(),
first_id,
second_id);
} else if (v->IsCompare()) {
@@ -1485,8 +1484,7 @@
LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) {
ASSERT(instr->value()->representation().IsTagged());
LOperand* value = UseTempRegister(instr->value());
-
- return DefineSameAsFirst(new LClassOfTest(value, TempRegister()));
+ return DefineSameAsFirst(new LClassOfTest(value));
}
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.h Tue Jan 11 04:10:11 2011
+++ /branches/bleeding_edge/src/arm/lithium-arm.h Tue Jan 11 06:01:53 2011
@@ -848,18 +848,12 @@
class LClassOfTest: public LUnaryOperation {
public:
- LClassOfTest(LOperand* value, LOperand* temp)
- : LUnaryOperation(value), temporary_(temp) {}
+ explicit LClassOfTest(LOperand* value) : LUnaryOperation(value) {}
DECLARE_CONCRETE_INSTRUCTION(ClassOfTest, "class-of-test")
DECLARE_HYDROGEN_ACCESSOR(ClassOfTest)
virtual void PrintDataTo(StringStream* stream) const;
-
- LOperand* temporary() { return temporary_; }
-
- private:
- LOperand *temporary_;
};
@@ -867,11 +861,10 @@
public:
LClassOfTestAndBranch(LOperand* value,
LOperand* temporary,
- LOperand* temporary2,
int true_block_id,
int false_block_id)
- : LClassOfTest(value, temporary),
- temporary2_(temporary2),
+ : LClassOfTest(value),
+ temporary_(temporary),
true_block_id_(true_block_id),
false_block_id_(false_block_id) { }
@@ -882,10 +875,10 @@
int true_block_id() const { return true_block_id_; }
int false_block_id() const { return false_block_id_; }
- LOperand* temporary2() { return temporary2_; }
+ LOperand* temporary() { return temporary_; }
private:
- LOperand* temporary2_;
+ LOperand* temporary_;
int true_block_id_;
int false_block_id_;
};
=======================================
--- /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 11
05:50:12 2011
+++ /branches/bleeding_edge/src/arm/lithium-codegen-arm.cc Tue Jan 11
06:01:53 2011
@@ -958,12 +958,26 @@
Register result = ToRegister(instr->result());
Register array = ToRegister(instr->input());
__ ldr(result, FieldMemOperand(array, FixedArray::kLengthOffset));
- Abort("DoFixedArrayLength untested.");
}
void LCodeGen::DoValueOf(LValueOf* instr) {
- Abort("DoValueOf unimplemented.");
+ Register input = ToRegister(instr->input());
+ Register result = ToRegister(instr->result());
+ Register map = ToRegister(instr->temporary());
+ ASSERT(input.is(result));
+ Label done;
+
+ // If the object is a smi return the object.
+ __ tst(input, Operand(kSmiTagMask));
+ __ b(eq, &done);
+
+ // If the object is not a value type, return the object.
+ __ CompareObjectType(input, map, map, JS_VALUE_TYPE);
+ __ b(ne, &done);
+ __ ldr(result, FieldMemOperand(input, JSValue::kValueOffset));
+
+ __ bind(&done);
}
@@ -971,7 +985,6 @@
LOperand* input = instr->input();
ASSERT(input->Equals(instr->result()));
__ mvn(ToRegister(input), Operand(ToRegister(input)));
- Abort("DoBitNotI untested.");
}
@@ -1408,7 +1421,7 @@
}
-// Branches to a label or falls through with the answer in the z flag.
Trashes
+// Branches to a label or falls through with the answer in flags. Trashes
// the temp registers, but not the input. Only input and temp2 may alias.
void LCodeGen::EmitClassOfTest(Label* is_true,
Label* is_false,
@@ -1416,17 +1429,91 @@
Register input,
Register temp,
Register temp2) {
- Abort("EmitClassOfTest unimplemented.");
+ ASSERT(!input.is(temp));
+ ASSERT(!temp.is(temp2)); // But input and temp2 may be the same
register.
+ __ tst(input, Operand(kSmiTagMask));
+ __ b(eq, is_false);
+ __ CompareObjectType(input, temp, temp2, FIRST_JS_OBJECT_TYPE);
+ __ b(lt, is_false);
+
+ // Map is now in temp.
+ // Functions have class 'Function'.
+ __ CompareInstanceType(temp, temp2, JS_FUNCTION_TYPE);
+ if (class_name->IsEqualTo(CStrVector("Function"))) {
+ __ b(eq, is_true);
+ } else {
+ __ b(eq, is_false);
+ }
+
+ // Check if the constructor in the map is a function.
+ __ ldr(temp, FieldMemOperand(temp, Map::kConstructorOffset));
+
+ // As long as JS_FUNCTION_TYPE is the last instance type and it is
+ // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
+ // LAST_JS_OBJECT_TYPE.
+ ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
+ ASSERT(JS_FUNCTION_TYPE == LAST_JS_OBJECT_TYPE + 1);
+
+ // Objects with a non-function constructor have class 'Object'.
+ __ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE);
+ if (class_name->IsEqualTo(CStrVector("Object"))) {
+ __ b(ne, is_true);
+ } else {
+ __ b(ne, is_false);
+ }
+
+ // temp now contains the constructor function. Grab the
+ // instance class name from there.
+ __ ldr(temp, FieldMemOperand(temp,
JSFunction::kSharedFunctionInfoOffset));
+ __ ldr(temp, FieldMemOperand(temp,
+
SharedFunctionInfo::kInstanceClassNameOffset));
+ // The class name we are testing against is a symbol because it's a
literal.
+ // The name in the constructor is a symbol because of the way the
context is
+ // booted. This routine isn't expected to work for random API-created
+ // classes and it doesn't have to because you can't access it with
natives
+ // syntax. Since both sides are symbols it is sufficient to use an
identity
+ // comparison.
+ __ cmp(temp, Operand(class_name));
+ // End with the answer in flags.
}
void LCodeGen::DoClassOfTest(LClassOfTest* instr) {
- Abort("DoClassOfTest unimplemented.");
+ Register input = ToRegister(instr->input());
+ Register result = ToRegister(instr->result());
+ ASSERT(input.is(result));
+ Handle<String> class_name = instr->hydrogen()->class_name();
+
+ Label done, is_true, is_false;
+
+ EmitClassOfTest(&is_true, &is_false, class_name, input, scratch0(),
input);
+ __ b(ne, &is_false);
+
+ __ bind(&is_true);
+ __ LoadRoot(result, Heap::kTrueValueRootIndex);
+ __ jmp(&done);
+
+ __ bind(&is_false);
+ __ LoadRoot(result, Heap::kFalseValueRootIndex);
+ __ bind(&done);
}
void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) {
- Abort("DoClassOfTestAndBranch unimplemented.");
+ Register input = ToRegister(instr->input());
+ Register temp = scratch0();
+ Register temp2 = ToRegister(instr->temporary());
+ Handle<String> class_name = instr->hydrogen()->class_name();
+
+ int true_block = chunk_->LookupDestination(instr->true_block_id());
+ int false_block = chunk_->LookupDestination(instr->false_block_id());
+
+ Label* true_label = chunk_->GetAssemblyLabel(true_block);
+ Label* false_label = chunk_->GetAssemblyLabel(false_block);
+
+ EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2);
+
+ EmitBranch(true_block, false_block, eq);
}
=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Jan 11 05:48:49 2011
+++ /branches/bleeding_edge/src/ia32/lithium-ia32.h Tue Jan 11 06:01:53 2011
@@ -898,7 +898,7 @@
LOperand* temporary() { return temporary_; }
private:
- LOperand *temporary_;
+ LOperand* temporary_;
};
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev