OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |