Index: src/arm/codegen-arm.cc |
=================================================================== |
--- src/arm/codegen-arm.cc (revision 2127) |
+++ src/arm/codegen-arm.cc (working copy) |
@@ -1503,9 +1503,7 @@ |
// Test for a Smi value in a HeapNumber. |
__ tst(r0, Operand(kSmiTagMask)); |
is_smi.Branch(eq); |
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
- __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
- __ cmp(r1, Operand(HEAP_NUMBER_TYPE)); |
+ __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); |
default_target->Branch(ne); |
frame_->EmitPush(r0); |
frame_->CallRuntime(Runtime::kNumberToSmi, 1); |
@@ -1872,9 +1870,7 @@ |
// Check if enumerable is already a JSObject |
__ tst(r0, Operand(kSmiTagMask)); |
primitive.Branch(eq); |
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
- __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
- __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); |
+ __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
jsobject.Branch(hs); |
primitive.Bind(); |
@@ -3281,11 +3277,8 @@ |
// if (object->IsSmi()) return the object. |
__ tst(r0, Operand(kSmiTagMask)); |
leave.Branch(eq); |
- // It is a heap object - get map. |
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
- __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
- // if (!object->IsJSValue()) return the object. |
- __ cmp(r1, Operand(JS_VALUE_TYPE)); |
+ // It is a heap object - get map. If (!object->IsJSValue()) return the object. |
+ __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE); |
leave.Branch(ne); |
// Load the value. |
__ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); |
@@ -3305,11 +3298,8 @@ |
// if (object->IsSmi()) return object. |
__ tst(r1, Operand(kSmiTagMask)); |
leave.Branch(eq); |
- // It is a heap object - get map. |
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
- // if (!object->IsJSValue()) return object. |
- __ cmp(r2, Operand(JS_VALUE_TYPE)); |
+ // It is a heap object - get map. If (!object->IsJSValue()) return the object. |
+ __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE); |
leave.Branch(ne); |
// Store the value. |
__ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); |
@@ -3381,11 +3371,8 @@ |
__ and_(r1, r0, Operand(kSmiTagMask)); |
__ eor(r1, r1, Operand(kSmiTagMask), SetCC); |
answer.Branch(ne); |
- // It is a heap object - get the map. |
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
- __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
- // Check if the object is a JS array or not. |
- __ cmp(r1, Operand(JS_ARRAY_TYPE)); |
+ // It is a heap object - get the map. Check if the object is a JS array. |
+ __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
answer.Bind(); |
cc_reg_ = eq; |
} |
@@ -4001,9 +3988,7 @@ |
} else if (check->Equals(Heap::function_symbol())) { |
__ tst(r1, Operand(kSmiTagMask)); |
false_target()->Branch(eq); |
- __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); |
- __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
- __ cmp(r1, Operand(JS_FUNCTION_TYPE)); |
+ __ CompareObjectType(r1, r1, r1, JS_FUNCTION_TYPE); |
cc_reg_ = eq; |
} else if (check->Equals(Heap::object_symbol())) { |
@@ -4076,13 +4061,9 @@ |
} |
case Token::INSTANCEOF: { |
- Result arg_count = allocator_->Allocate(r0); |
- ASSERT(arg_count.is_valid()); |
- __ mov(arg_count.reg(), Operand(1)); // not counting receiver |
- Result result = frame_->InvokeBuiltin(Builtins::INSTANCE_OF, |
- CALL_JS, |
- &arg_count, |
- 2); |
+ InstanceofStub stub; |
+ Result result = frame_->CallStub(&stub, 2); |
+ // At this point if instanceof succeeded then r0 == 0. |
__ tst(result.reg(), Operand(result.reg())); |
cc_reg_ = eq; |
break; |
@@ -5056,6 +5037,68 @@ |
} |
+// This stub performs an instanceof, calling the builtin function if |
+// necessary. Uses r1 for the object, r0 for the function that it may |
+// be an instance of (these are fetched from the stack). |
+void InstanceofStub::Generate(MacroAssembler* masm) { |
+ // Get the object - slow case for smis (we may need to throw an exception |
+ // depending on the rhs). |
+ Label slow, loop, is_instance, is_not_instance; |
+ __ ldr(r0, MemOperand(sp, 1 * kPointerSize)); |
+ __ BranchOnSmi(r0, &slow); |
+ |
+ // Check that the left hand is a JS object and put map in r3. |
+ __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset)); |
+ __ ldrb(r2, FieldMemOperand(r3, Map::kInstanceTypeOffset)); |
+ __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); |
+ __ b(lt, &slow); |
+ __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE)); |
+ __ b(gt, &slow); |
+ |
+ // Get the prototype of the function (r4 is result, r2 is scratch). |
+ __ ldr(r1, MemOperand(sp, 0 * kPointerSize)); |
+ __ TryGetFunctionPrototype(r1, r4, r2, &slow); |
+ |
+ // Check that the function prototype is a JS object. |
+ __ BranchOnSmi(r4, &slow); |
+ __ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE); |
+ __ b(lt, &slow); |
+ __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE)); |
+ __ b(gt, &slow); |
+ |
+ // Register mapping: r3 is object map and r4 is function prototype. |
+ // Get prototype of object into r2. |
+ __ ldr(r2, FieldMemOperand(r3, Map::kPrototypeOffset)); |
+ |
+ // Loop through the prototype chain looking for the function prototype. |
+ __ bind(&loop); |
+ __ cmp(r2, Operand(r4)); |
+ __ b(eq, &is_instance); |
+ __ cmp(r2, Operand(Factory::null_value())); |
+ __ b(eq, &is_not_instance); |
+ __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset)); |
+ __ ldr(r2, FieldMemOperand(r2, Map::kPrototypeOffset)); |
+ __ jmp(&loop); |
+ |
+ __ bind(&is_instance); |
+ __ mov(r0, Operand(Smi::FromInt(0))); |
+ __ pop(); |
+ __ pop(); |
+ __ mov(pc, Operand(lr)); // Return. |
+ |
+ __ bind(&is_not_instance); |
+ __ mov(r0, Operand(Smi::FromInt(1))); |
+ __ pop(); |
+ __ pop(); |
+ __ mov(pc, Operand(lr)); // Return. |
+ |
+ // Slow-case. Tail call builtin. |
+ __ bind(&slow); |
+ __ mov(r0, Operand(1)); // Arg count without receiver. |
+ __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS); |
+} |
+ |
+ |
void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
// Check if the calling frame is an arguments adaptor frame. |
Label adaptor; |
@@ -5084,8 +5127,7 @@ |
// Check that the key is a smi. |
Label slow; |
- __ tst(r1, Operand(kSmiTagMask)); |
- __ b(ne, &slow); |
+ __ BranchOnNotSmi(r1, &slow); |
// Check if the calling frame is an arguments adaptor frame. |
Label adaptor; |
@@ -5157,12 +5199,9 @@ |
// Check that the function is really a JavaScript function. |
// r1: pushed function (to be verified) |
- __ tst(r1, Operand(kSmiTagMask)); |
- __ b(eq, &slow); |
+ __ BranchOnSmi(r1, &slow); |
// Get the map of the function object. |
- __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); |
- __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
- __ cmp(r2, Operand(JS_FUNCTION_TYPE)); |
+ __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
__ b(ne, &slow); |
// Fast-case: Invoke the function now. |