Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 119353: Add instanceof stub for ARM. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/builtins-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1485 matching lines...) Expand 10 before | Expand all | Expand 10 after
1496 // "default" for failure to hit the jump table. 1496 // "default" for failure to hit the jump table.
1497 JumpTarget* default_target = 1497 JumpTarget* default_target =
1498 (default_label == NULL) ? node->break_target() : &setup_default; 1498 (default_label == NULL) ? node->break_target() : &setup_default;
1499 1499
1500 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2); 1500 ASSERT(kSmiTag == 0 && kSmiTagSize <= 2);
1501 frame_->EmitPop(r0); 1501 frame_->EmitPop(r0);
1502 1502
1503 // Test for a Smi value in a HeapNumber. 1503 // Test for a Smi value in a HeapNumber.
1504 __ tst(r0, Operand(kSmiTagMask)); 1504 __ tst(r0, Operand(kSmiTagMask));
1505 is_smi.Branch(eq); 1505 is_smi.Branch(eq);
1506 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1506 __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE);
1507 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
1508 __ cmp(r1, Operand(HEAP_NUMBER_TYPE));
1509 default_target->Branch(ne); 1507 default_target->Branch(ne);
1510 frame_->EmitPush(r0); 1508 frame_->EmitPush(r0);
1511 frame_->CallRuntime(Runtime::kNumberToSmi, 1); 1509 frame_->CallRuntime(Runtime::kNumberToSmi, 1);
1512 is_smi.Bind(); 1510 is_smi.Bind();
1513 1511
1514 if (min_index != 0) { 1512 if (min_index != 0) {
1515 // Small positive numbers can be immediate operands. 1513 // Small positive numbers can be immediate operands.
1516 if (min_index < 0) { 1514 if (min_index < 0) {
1517 // If min_index is Smi::kMinValue, -min_index is not a Smi. 1515 // If min_index is Smi::kMinValue, -min_index is not a Smi.
1518 if (Smi::IsValid(-min_index)) { 1516 if (Smi::IsValid(-min_index)) {
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
1865 // Stack layout in body: 1863 // Stack layout in body:
1866 // [iteration counter (Smi)] 1864 // [iteration counter (Smi)]
1867 // [length of array] 1865 // [length of array]
1868 // [FixedArray] 1866 // [FixedArray]
1869 // [Map or 0] 1867 // [Map or 0]
1870 // [Object] 1868 // [Object]
1871 1869
1872 // Check if enumerable is already a JSObject 1870 // Check if enumerable is already a JSObject
1873 __ tst(r0, Operand(kSmiTagMask)); 1871 __ tst(r0, Operand(kSmiTagMask));
1874 primitive.Branch(eq); 1872 primitive.Branch(eq);
1875 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 1873 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE);
1876 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
1877 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
1878 jsobject.Branch(hs); 1874 jsobject.Branch(hs);
1879 1875
1880 primitive.Bind(); 1876 primitive.Bind();
1881 frame_->EmitPush(r0); 1877 frame_->EmitPush(r0);
1882 Result arg_count = allocator_->Allocate(r0); 1878 Result arg_count = allocator_->Allocate(r0);
1883 ASSERT(arg_count.is_valid()); 1879 ASSERT(arg_count.is_valid());
1884 __ mov(arg_count.reg(), Operand(0)); 1880 __ mov(arg_count.reg(), Operand(0));
1885 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1); 1881 frame_->InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS, &arg_count, 1);
1886 1882
1887 jsobject.Bind(); 1883 jsobject.Bind();
(...skipping 1386 matching lines...) Expand 10 before | Expand all | Expand 10 after
3274 3270
3275 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { 3271 void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) {
3276 VirtualFrame::SpilledScope spilled_scope; 3272 VirtualFrame::SpilledScope spilled_scope;
3277 ASSERT(args->length() == 1); 3273 ASSERT(args->length() == 1);
3278 JumpTarget leave; 3274 JumpTarget leave;
3279 LoadAndSpill(args->at(0)); 3275 LoadAndSpill(args->at(0));
3280 frame_->EmitPop(r0); // r0 contains object. 3276 frame_->EmitPop(r0); // r0 contains object.
3281 // if (object->IsSmi()) return the object. 3277 // if (object->IsSmi()) return the object.
3282 __ tst(r0, Operand(kSmiTagMask)); 3278 __ tst(r0, Operand(kSmiTagMask));
3283 leave.Branch(eq); 3279 leave.Branch(eq);
3284 // It is a heap object - get map. 3280 // It is a heap object - get map. If (!object->IsJSValue()) return the object.
3285 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3281 __ CompareObjectType(r0, r1, r1, JS_VALUE_TYPE);
3286 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3287 // if (!object->IsJSValue()) return the object.
3288 __ cmp(r1, Operand(JS_VALUE_TYPE));
3289 leave.Branch(ne); 3282 leave.Branch(ne);
3290 // Load the value. 3283 // Load the value.
3291 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset)); 3284 __ ldr(r0, FieldMemOperand(r0, JSValue::kValueOffset));
3292 leave.Bind(); 3285 leave.Bind();
3293 frame_->EmitPush(r0); 3286 frame_->EmitPush(r0);
3294 } 3287 }
3295 3288
3296 3289
3297 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { 3290 void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) {
3298 VirtualFrame::SpilledScope spilled_scope; 3291 VirtualFrame::SpilledScope spilled_scope;
3299 ASSERT(args->length() == 2); 3292 ASSERT(args->length() == 2);
3300 JumpTarget leave; 3293 JumpTarget leave;
3301 LoadAndSpill(args->at(0)); // Load the object. 3294 LoadAndSpill(args->at(0)); // Load the object.
3302 LoadAndSpill(args->at(1)); // Load the value. 3295 LoadAndSpill(args->at(1)); // Load the value.
3303 frame_->EmitPop(r0); // r0 contains value 3296 frame_->EmitPop(r0); // r0 contains value
3304 frame_->EmitPop(r1); // r1 contains object 3297 frame_->EmitPop(r1); // r1 contains object
3305 // if (object->IsSmi()) return object. 3298 // if (object->IsSmi()) return object.
3306 __ tst(r1, Operand(kSmiTagMask)); 3299 __ tst(r1, Operand(kSmiTagMask));
3307 leave.Branch(eq); 3300 leave.Branch(eq);
3308 // It is a heap object - get map. 3301 // It is a heap object - get map. If (!object->IsJSValue()) return the object.
3309 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3302 __ CompareObjectType(r1, r2, r2, JS_VALUE_TYPE);
3310 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
3311 // if (!object->IsJSValue()) return object.
3312 __ cmp(r2, Operand(JS_VALUE_TYPE));
3313 leave.Branch(ne); 3303 leave.Branch(ne);
3314 // Store the value. 3304 // Store the value.
3315 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset)); 3305 __ str(r0, FieldMemOperand(r1, JSValue::kValueOffset));
3316 // Update the write barrier. 3306 // Update the write barrier.
3317 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag)); 3307 __ mov(r2, Operand(JSValue::kValueOffset - kHeapObjectTag));
3318 __ RecordWrite(r1, r2, r3); 3308 __ RecordWrite(r1, r2, r3);
3319 // Leave. 3309 // Leave.
3320 leave.Bind(); 3310 leave.Bind();
3321 frame_->EmitPush(r0); 3311 frame_->EmitPush(r0);
3322 } 3312 }
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3374 ASSERT(args->length() == 1); 3364 ASSERT(args->length() == 1);
3375 LoadAndSpill(args->at(0)); 3365 LoadAndSpill(args->at(0));
3376 JumpTarget answer; 3366 JumpTarget answer;
3377 // We need the CC bits to come out as not_equal in the case where the 3367 // We need the CC bits to come out as not_equal in the case where the
3378 // object is a smi. This can't be done with the usual test opcode so 3368 // object is a smi. This can't be done with the usual test opcode so
3379 // we use XOR to get the right CC bits. 3369 // we use XOR to get the right CC bits.
3380 frame_->EmitPop(r0); 3370 frame_->EmitPop(r0);
3381 __ and_(r1, r0, Operand(kSmiTagMask)); 3371 __ and_(r1, r0, Operand(kSmiTagMask));
3382 __ eor(r1, r1, Operand(kSmiTagMask), SetCC); 3372 __ eor(r1, r1, Operand(kSmiTagMask), SetCC);
3383 answer.Branch(ne); 3373 answer.Branch(ne);
3384 // It is a heap object - get the map. 3374 // It is a heap object - get the map. Check if the object is a JS array.
3385 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 3375 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE);
3386 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
3387 // Check if the object is a JS array or not.
3388 __ cmp(r1, Operand(JS_ARRAY_TYPE));
3389 answer.Bind(); 3376 answer.Bind();
3390 cc_reg_ = eq; 3377 cc_reg_ = eq;
3391 } 3378 }
3392 3379
3393 3380
3394 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { 3381 void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) {
3395 VirtualFrame::SpilledScope spilled_scope; 3382 VirtualFrame::SpilledScope spilled_scope;
3396 ASSERT(args->length() == 0); 3383 ASSERT(args->length() == 0);
3397 3384
3398 // Seed the result with the formal parameters count, which will be used 3385 // Seed the result with the formal parameters count, which will be used
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
3994 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3981 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
3995 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset)); 3982 __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
3996 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable)); 3983 __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
3997 __ cmp(r2, Operand(1 << Map::kIsUndetectable)); 3984 __ cmp(r2, Operand(1 << Map::kIsUndetectable));
3998 3985
3999 cc_reg_ = eq; 3986 cc_reg_ = eq;
4000 3987
4001 } else if (check->Equals(Heap::function_symbol())) { 3988 } else if (check->Equals(Heap::function_symbol())) {
4002 __ tst(r1, Operand(kSmiTagMask)); 3989 __ tst(r1, Operand(kSmiTagMask));
4003 false_target()->Branch(eq); 3990 false_target()->Branch(eq);
4004 __ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset)); 3991 __ CompareObjectType(r1, r1, r1, JS_FUNCTION_TYPE);
4005 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
4006 __ cmp(r1, Operand(JS_FUNCTION_TYPE));
4007 cc_reg_ = eq; 3992 cc_reg_ = eq;
4008 3993
4009 } else if (check->Equals(Heap::object_symbol())) { 3994 } else if (check->Equals(Heap::object_symbol())) {
4010 __ tst(r1, Operand(kSmiTagMask)); 3995 __ tst(r1, Operand(kSmiTagMask));
4011 false_target()->Branch(eq); 3996 false_target()->Branch(eq);
4012 3997
4013 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3998 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
4014 __ cmp(r1, Operand(Factory::null_value())); 3999 __ cmp(r1, Operand(Factory::null_value()));
4015 true_target()->Branch(eq); 4000 true_target()->Branch(eq);
4016 4001
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
4069 __ mov(arg_count.reg(), Operand(1)); // not counting receiver 4054 __ mov(arg_count.reg(), Operand(1)); // not counting receiver
4070 Result result = frame_->InvokeBuiltin(Builtins::IN, 4055 Result result = frame_->InvokeBuiltin(Builtins::IN,
4071 CALL_JS, 4056 CALL_JS,
4072 &arg_count, 4057 &arg_count,
4073 2); 4058 2);
4074 frame_->EmitPush(result.reg()); 4059 frame_->EmitPush(result.reg());
4075 break; 4060 break;
4076 } 4061 }
4077 4062
4078 case Token::INSTANCEOF: { 4063 case Token::INSTANCEOF: {
4079 Result arg_count = allocator_->Allocate(r0); 4064 InstanceofStub stub;
4080 ASSERT(arg_count.is_valid()); 4065 Result result = frame_->CallStub(&stub, 2);
4081 __ mov(arg_count.reg(), Operand(1)); // not counting receiver 4066 // At this point if instanceof succeeded then r0 == 0.
4082 Result result = frame_->InvokeBuiltin(Builtins::INSTANCE_OF,
4083 CALL_JS,
4084 &arg_count,
4085 2);
4086 __ tst(result.reg(), Operand(result.reg())); 4067 __ tst(result.reg(), Operand(result.reg()));
4087 cc_reg_ = eq; 4068 cc_reg_ = eq;
4088 break; 4069 break;
4089 } 4070 }
4090 4071
4091 default: 4072 default:
4092 UNREACHABLE(); 4073 UNREACHABLE();
4093 } 4074 }
4094 ASSERT((has_cc() && frame_->height() == original_height) || 4075 ASSERT((has_cc() && frame_->height() == original_height) ||
4095 (!has_cc() && frame_->height() == original_height + 1)); 4076 (!has_cc() && frame_->height() == original_height + 1));
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after
5049 // Restore callee-saved registers and return. 5030 // Restore callee-saved registers and return.
5050 #ifdef DEBUG 5031 #ifdef DEBUG
5051 if (FLAG_debug_code) { 5032 if (FLAG_debug_code) {
5052 __ mov(lr, Operand(pc)); 5033 __ mov(lr, Operand(pc));
5053 } 5034 }
5054 #endif 5035 #endif
5055 __ ldm(ia_w, sp, kCalleeSaved | pc.bit()); 5036 __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
5056 } 5037 }
5057 5038
5058 5039
5040 // This stub performs an instanceof, calling the builtin function if
5041 // necessary. Uses r1 for the object, r0 for the function that it may
5042 // be an instance of (these are fetched from the stack).
5043 void InstanceofStub::Generate(MacroAssembler* masm) {
5044 // Get the object - slow case for smis (we may need to throw an exception
5045 // depending on the rhs).
5046 Label slow, loop, is_instance, is_not_instance;
5047 __ ldr(r0, MemOperand(sp, 1 * kPointerSize));
5048 __ BranchOnSmi(r0, &slow);
5049
5050 // Check that the left hand is a JS object and put map in r3.
5051 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
5052 __ ldrb(r2, FieldMemOperand(r3, Map::kInstanceTypeOffset));
5053 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
5054 __ b(lt, &slow);
5055 __ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
5056 __ b(gt, &slow);
5057
5058 // Get the prototype of the function (r4 is result, r2 is scratch).
5059 __ ldr(r1, MemOperand(sp, 0 * kPointerSize));
5060 __ TryGetFunctionPrototype(r1, r4, r2, &slow);
5061
5062 // Check that the function prototype is a JS object.
5063 __ BranchOnSmi(r4, &slow);
5064 __ CompareObjectType(r4, r5, r5, FIRST_JS_OBJECT_TYPE);
5065 __ b(lt, &slow);
5066 __ cmp(r5, Operand(LAST_JS_OBJECT_TYPE));
5067 __ b(gt, &slow);
5068
5069 // Register mapping: r3 is object map and r4 is function prototype.
5070 // Get prototype of object into r2.
5071 __ ldr(r2, FieldMemOperand(r3, Map::kPrototypeOffset));
5072
5073 // Loop through the prototype chain looking for the function prototype.
5074 __ bind(&loop);
5075 __ cmp(r2, Operand(r4));
5076 __ b(eq, &is_instance);
5077 __ cmp(r2, Operand(Factory::null_value()));
5078 __ b(eq, &is_not_instance);
5079 __ ldr(r2, FieldMemOperand(r2, HeapObject::kMapOffset));
5080 __ ldr(r2, FieldMemOperand(r2, Map::kPrototypeOffset));
5081 __ jmp(&loop);
5082
5083 __ bind(&is_instance);
5084 __ mov(r0, Operand(Smi::FromInt(0)));
5085 __ pop();
5086 __ pop();
5087 __ mov(pc, Operand(lr)); // Return.
5088
5089 __ bind(&is_not_instance);
5090 __ mov(r0, Operand(Smi::FromInt(1)));
5091 __ pop();
5092 __ pop();
5093 __ mov(pc, Operand(lr)); // Return.
5094
5095 // Slow-case. Tail call builtin.
5096 __ bind(&slow);
5097 __ mov(r0, Operand(1)); // Arg count without receiver.
5098 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_JS);
5099 }
5100
5101
5059 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { 5102 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
5060 // Check if the calling frame is an arguments adaptor frame. 5103 // Check if the calling frame is an arguments adaptor frame.
5061 Label adaptor; 5104 Label adaptor;
5062 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 5105 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5063 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 5106 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
5064 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); 5107 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));
5065 __ b(eq, &adaptor); 5108 __ b(eq, &adaptor);
5066 5109
5067 // Nothing to do: The formal number of parameters has already been 5110 // Nothing to do: The formal number of parameters has already been
5068 // passed in register r0 by calling function. Just return it. 5111 // passed in register r0 by calling function. Just return it.
5069 __ Jump(lr); 5112 __ Jump(lr);
5070 5113
5071 // Arguments adaptor case: Read the arguments length from the 5114 // Arguments adaptor case: Read the arguments length from the
5072 // adaptor frame and return it. 5115 // adaptor frame and return it.
5073 __ bind(&adaptor); 5116 __ bind(&adaptor);
5074 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset)); 5117 __ ldr(r0, MemOperand(r2, ArgumentsAdaptorFrameConstants::kLengthOffset));
5075 __ Jump(lr); 5118 __ Jump(lr);
5076 } 5119 }
5077 5120
5078 5121
5079 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 5122 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
5080 // The displacement is the offset of the last parameter (if any) 5123 // The displacement is the offset of the last parameter (if any)
5081 // relative to the frame pointer. 5124 // relative to the frame pointer.
5082 static const int kDisplacement = 5125 static const int kDisplacement =
5083 StandardFrameConstants::kCallerSPOffset - kPointerSize; 5126 StandardFrameConstants::kCallerSPOffset - kPointerSize;
5084 5127
5085 // Check that the key is a smi. 5128 // Check that the key is a smi.
5086 Label slow; 5129 Label slow;
5087 __ tst(r1, Operand(kSmiTagMask)); 5130 __ BranchOnNotSmi(r1, &slow);
5088 __ b(ne, &slow);
5089 5131
5090 // Check if the calling frame is an arguments adaptor frame. 5132 // Check if the calling frame is an arguments adaptor frame.
5091 Label adaptor; 5133 Label adaptor;
5092 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); 5134 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
5093 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset)); 5135 __ ldr(r3, MemOperand(r2, StandardFrameConstants::kContextOffset));
5094 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL)); 5136 __ cmp(r3, Operand(ArgumentsAdaptorFrame::SENTINEL));
5095 __ b(eq, &adaptor); 5137 __ b(eq, &adaptor);
5096 5138
5097 // Check index against formal parameters count limit passed in 5139 // Check index against formal parameters count limit passed in
5098 // through register eax. Use unsigned comparison to get negative 5140 // through register eax. Use unsigned comparison to get negative
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
5150 5192
5151 5193
5152 void CallFunctionStub::Generate(MacroAssembler* masm) { 5194 void CallFunctionStub::Generate(MacroAssembler* masm) {
5153 Label slow; 5195 Label slow;
5154 // Get the function to call from the stack. 5196 // Get the function to call from the stack.
5155 // function, receiver [, arguments] 5197 // function, receiver [, arguments]
5156 __ ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize)); 5198 __ ldr(r1, MemOperand(sp, (argc_ + 1) * kPointerSize));
5157 5199
5158 // Check that the function is really a JavaScript function. 5200 // Check that the function is really a JavaScript function.
5159 // r1: pushed function (to be verified) 5201 // r1: pushed function (to be verified)
5160 __ tst(r1, Operand(kSmiTagMask)); 5202 __ BranchOnSmi(r1, &slow);
5161 __ b(eq, &slow);
5162 // Get the map of the function object. 5203 // Get the map of the function object.
5163 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 5204 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE);
5164 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
5165 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
5166 __ b(ne, &slow); 5205 __ b(ne, &slow);
5167 5206
5168 // Fast-case: Invoke the function now. 5207 // Fast-case: Invoke the function now.
5169 // r1: pushed function 5208 // r1: pushed function
5170 ParameterCount actual(argc_); 5209 ParameterCount actual(argc_);
5171 __ InvokeFunction(r1, actual, JUMP_FUNCTION); 5210 __ InvokeFunction(r1, actual, JUMP_FUNCTION);
5172 5211
5173 // Slow-case: Non-function called. 5212 // Slow-case: Non-function called.
5174 __ bind(&slow); 5213 __ bind(&slow);
5175 __ mov(r0, Operand(argc_)); // Setup the number of arguments. 5214 __ mov(r0, Operand(argc_)); // Setup the number of arguments.
5176 __ mov(r2, Operand(0)); 5215 __ mov(r2, Operand(0));
5177 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION); 5216 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
5178 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)), 5217 __ Jump(Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)),
5179 RelocInfo::CODE_TARGET); 5218 RelocInfo::CODE_TARGET);
5180 } 5219 }
5181 5220
5182 5221
5183 #undef __ 5222 #undef __
5184 5223
5185 } } // namespace v8::internal 5224 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/builtins-arm.cc ('k') | src/arm/ic-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698