Commit 8bd85d8c authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

Add instanceof stub for ARM.

Review URL: http://codereview.chromium.org/119353

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2132 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b7d48f58
......@@ -64,9 +64,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &non_function_call);
// Check that the function is a JSFunction.
__ 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, &non_function_call);
// Enter a construct frame.
......@@ -159,9 +157,7 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
// If the type of the result (stored in its map) is less than
// FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
__ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
__ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
__ CompareObjectType(r0, r3, r3, FIRST_JS_OBJECT_TYPE);
__ b(ge, &exit);
// Throw away the result of the constructor invocation and use the
......@@ -290,9 +286,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &non_function);
__ 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(eq, &function);
// Non-function called: Clear the function to force exception.
......@@ -328,9 +322,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ cmp(r2, r3);
__ b(eq, &use_global_receiver);
__ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
__ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
__ CompareObjectType(r2, r3, r3, FIRST_JS_OBJECT_TYPE);
__ b(lt, &call_to_object);
__ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
__ b(le, &done);
......@@ -501,9 +493,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
// Check if the receiver is already a JavaScript object.
// r0: receiver
__ 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);
__ b(lt, &call_to_object);
__ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
__ b(le, &push_receiver);
......
This diff is collapsed.
......@@ -223,9 +223,7 @@ void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
// Check for number.
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &number);
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
__ cmp(r3, Operand(HEAP_NUMBER_TYPE));
__ CompareObjectType(r1, r3, r3, HEAP_NUMBER_TYPE);
__ b(ne, &non_number);
__ bind(&number);
StubCompiler::GenerateLoadGlobalFunctionPrototype(
......@@ -272,9 +270,7 @@ static void GenerateNormalHelper(MacroAssembler* masm,
__ b(eq, miss);
// Check that the value is a JSFunction.
__ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset));
__ cmp(r0, Operand(JS_FUNCTION_TYPE));
__ CompareObjectType(r1, r0, r0, JS_FUNCTION_TYPE);
__ b(ne, miss);
// Check that the function has been loaded.
......@@ -312,10 +308,8 @@ void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &miss);
// Check that the receiver is a valid JS object.
__ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r0, FieldMemOperand(r3, Map::kInstanceTypeOffset));
__ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE));
// Check that the receiver is a valid JS object. Put the map in r3.
__ CompareObjectType(r1, r3, r0, FIRST_JS_OBJECT_TYPE);
__ b(lt, &miss);
// If this assert fails, we have to check upper bound too.
......@@ -392,9 +386,7 @@ void CallIC::Generate(MacroAssembler* masm,
__ ldr(r2, MemOperand(sp, argc * kPointerSize)); // receiver
__ tst(r2, Operand(kSmiTagMask));
__ b(eq, &invoke);
__ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
__ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
__ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE));
__ CompareObjectType(r2, r3, r3, JS_GLOBAL_OBJECT_TYPE);
__ b(eq, &global);
__ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE));
__ b(ne, &invoke);
......@@ -447,10 +439,8 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
__ tst(r0, Operand(kSmiTagMask));
__ b(eq, &miss);
// Check that the receiver is a valid JS object.
__ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r1, FieldMemOperand(r3, Map::kInstanceTypeOffset));
__ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
// Check that the receiver is a valid JS object. Put the map in r3.
__ CompareObjectType(r0, r3, r1, FIRST_JS_OBJECT_TYPE);
__ b(lt, &miss);
// If this assert fails, we have to check upper bound too.
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
......
......@@ -750,6 +750,62 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
}
void MacroAssembler::CompareObjectType(Register function,
Register map,
Register type_reg,
InstanceType type) {
ldr(map, FieldMemOperand(function, HeapObject::kMapOffset));
ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
cmp(type_reg, Operand(type));
}
void MacroAssembler::TryGetFunctionPrototype(Register function,
Register result,
Register scratch,
Label* miss) {
// Check that the receiver isn't a smi.
BranchOnSmi(function, miss);
// Check that the function really is a function. Load map into result reg.
CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
b(ne, miss);
// Make sure that the function has an instance prototype.
Label non_instance;
ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
b(ne, &non_instance);
// Get the prototype or initial map from the function.
ldr(result,
FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
// If the prototype or initial map is the hole, don't return it and
// simply miss the cache instead. This will allow us to allocate a
// prototype object on-demand in the runtime system.
cmp(result, Operand(Factory::the_hole_value()));
b(eq, miss);
// If the function does not have an initial map, we're done.
Label done;
CompareObjectType(result, scratch, scratch, MAP_TYPE);
b(ne, &done);
// Get the prototype from the initial map.
ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
jmp(&done);
// Non-instance prototype: Fetch prototype from constructor field
// in initial map.
bind(&non_instance);
ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
// All done.
bind(&done);
}
void MacroAssembler::CallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs
Call(stub->GetCode(), RelocInfo::CODE_TARGET);
......
......@@ -187,6 +187,38 @@ class MacroAssembler: public Assembler {
// ---------------------------------------------------------------------------
// Support functions.
// Try to get function prototype of a function and puts the value in
// the result register. Checks that the function really is a
// function and jumps to the miss label if the fast checks fail. The
// function register will be untouched; the other registers may be
// clobbered.
void TryGetFunctionPrototype(Register function,
Register result,
Register scratch,
Label* miss);
// Compare object type for heap object. heap_object contains a non-Smi
// whose object type should be compared with the given type. This both
// sets the flags and leaves the object type in the type_reg register.
// It leaves the map in the map register (unless the type_reg and map register
// are the same register). It leaves the heap object in the heap_object
// register unless the heap_object register is the same register as one of the
// other // registers.
void CompareObjectType(Register heap_object,
Register map,
Register type_reg,
InstanceType type);
inline void BranchOnSmi(Register value, Label* smi_label) {
tst(value, Operand(kSmiTagMask));
b(eq, smi_label);
}
inline void BranchOnNotSmi(Register value, Label* not_smi_label) {
tst(value, Operand(kSmiTagMask));
b(ne, not_smi_label);
}
// Generates code for reporting that an illegal operation has
// occurred.
void IllegalOperation(int num_arguments);
......
......@@ -283,9 +283,7 @@ void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
__ b(eq, miss_label);
// Check that the object is a JS array.
__ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
__ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
__ cmp(scratch, Operand(JS_ARRAY_TYPE));
__ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
__ b(ne, miss_label);
// Load length directly from the JS array.
......@@ -523,9 +521,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &miss);
// Get the map.
__ 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, &miss);
// Patch the receiver on the stack with the global proxy if
......@@ -588,9 +584,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
case STRING_CHECK:
// Check that the object is a two-byte string or a symbol.
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
__ cmp(r2, Operand(FIRST_NONSTRING_TYPE));
__ CompareObjectType(r1, r2, r2, FIRST_NONSTRING_TYPE);
__ b(hs, &miss);
// Check that the maps starting from the prototype haven't changed.
GenerateLoadGlobalFunctionPrototype(masm(),
......@@ -605,9 +599,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// Check that the object is a smi or a heap number.
__ tst(r1, Operand(kSmiTagMask));
__ b(eq, &fast);
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
__ cmp(r2, Operand(HEAP_NUMBER_TYPE));
__ CompareObjectType(r1, r2, r2, HEAP_NUMBER_TYPE);
__ b(ne, &miss);
__ bind(&fast);
// Check that the maps starting from the prototype haven't changed.
......
......@@ -156,9 +156,7 @@ void VirtualFrame::Enter() {
__ b(ne, &map_check);
__ stop("VirtualFrame::Enter - r1 is not a function (smi check).");
__ bind(&map_check);
__ 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(eq, &done);
__ stop("VirtualFrame::Enter - r1 is not a function (map check).");
__ bind(&done);
......
......@@ -228,6 +228,18 @@ class StackCheckStub : public CodeStub {
};
class InstanceofStub: public CodeStub {
public:
InstanceofStub() { }
void Generate(MacroAssembler* masm);
private:
Major MajorKey() { return Instanceof; }
int MinorKey() { return 0; }
};
class UnarySubStub : public CodeStub {
public:
explicit UnarySubStub(bool overwrite)
......
......@@ -5466,18 +5466,6 @@ void CodeGenerator::VisitThisFunction(ThisFunction* node) {
}
class InstanceofStub: public CodeStub {
public:
InstanceofStub() { }
void Generate(MacroAssembler* masm);
private:
Major MajorKey() { return Instanceof; }
int MinorKey() { return 0; }
};
void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
Comment cmnt(masm_, "[ CompareOperation");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment