| 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 |