OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 // Check that the properties array is a dictionary. | 88 // Check that the properties array is a dictionary. |
89 __ movq(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); | 89 __ movq(r0, FieldOperand(r1, JSObject::kPropertiesOffset)); |
90 __ Cmp(FieldOperand(r0, HeapObject::kMapOffset), Factory::hash_table_map()); | 90 __ Cmp(FieldOperand(r0, HeapObject::kMapOffset), Factory::hash_table_map()); |
91 __ j(not_equal, miss_label); | 91 __ j(not_equal, miss_label); |
92 | 92 |
93 // Compute the capacity mask. | 93 // Compute the capacity mask. |
94 const int kCapacityOffset = | 94 const int kCapacityOffset = |
95 StringDictionary::kHeaderSize + | 95 StringDictionary::kHeaderSize + |
96 StringDictionary::kCapacityIndex * kPointerSize; | 96 StringDictionary::kCapacityIndex * kPointerSize; |
97 __ movq(r2, FieldOperand(r0, kCapacityOffset)); | 97 __ movq(r2, FieldOperand(r0, kCapacityOffset)); |
98 __ shrl(r2, Immediate(kSmiTagSize)); // convert smi to int | 98 __ SmiToInteger32(r2, r2); |
99 __ decl(r2); | 99 __ decl(r2); |
100 | 100 |
101 // Generate an unrolled loop that performs a few probes before | 101 // Generate an unrolled loop that performs a few probes before |
102 // giving up. Measurements done on Gmail indicate that 2 probes | 102 // giving up. Measurements done on Gmail indicate that 2 probes |
103 // cover ~93% of loads from dictionaries. | 103 // cover ~93% of loads from dictionaries. |
104 static const int kProbes = 4; | 104 static const int kProbes = 4; |
105 const int kElementsStartOffset = | 105 const int kElementsStartOffset = |
106 StringDictionary::kHeaderSize + | 106 StringDictionary::kHeaderSize + |
107 StringDictionary::kElementsStartIndex * kPointerSize; | 107 StringDictionary::kElementsStartIndex * kPointerSize; |
108 for (int i = 0; i < kProbes; i++) { | 108 for (int i = 0; i < kProbes; i++) { |
(...skipping 16 matching lines...) Expand all Loading... |
125 __ j(equal, &done); | 125 __ j(equal, &done); |
126 } else { | 126 } else { |
127 __ j(not_equal, miss_label); | 127 __ j(not_equal, miss_label); |
128 } | 128 } |
129 } | 129 } |
130 | 130 |
131 // Check that the value is a normal property. | 131 // Check that the value is a normal property. |
132 __ bind(&done); | 132 __ bind(&done); |
133 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | 133 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
134 __ testl(Operand(r0, r1, times_pointer_size, kDetailsOffset - kHeapObjectTag), | 134 __ testl(Operand(r0, r1, times_pointer_size, kDetailsOffset - kHeapObjectTag), |
135 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 135 Immediate(Smi::FromInt(PropertyDetails::TypeField::mask()))); |
136 __ j(not_zero, miss_label); | 136 __ j(not_zero, miss_label); |
137 | 137 |
138 // Get the value at the masked, scaled index. | 138 // Get the value at the masked, scaled index. |
139 const int kValueOffset = kElementsStartOffset + kPointerSize; | 139 const int kValueOffset = kElementsStartOffset + kPointerSize; |
140 __ movq(r1, | 140 __ movq(r1, |
141 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); | 141 Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); |
142 } | 142 } |
143 | 143 |
144 | 144 |
145 // Helper function used to check that a value is either not an object | 145 // Helper function used to check that a value is either not an object |
146 // or is loaded if it is an object. | 146 // or is loaded if it is an object. |
147 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss, | 147 static void GenerateCheckNonObjectOrLoaded(MacroAssembler* masm, Label* miss, |
148 Register value) { | 148 Register value) { |
149 Label done; | 149 Label done; |
150 // Check if the value is a Smi. | 150 // Check if the value is a Smi. |
151 __ testl(value, Immediate(kSmiTagMask)); | 151 __ JumpIfSmi(value, &done); |
152 __ j(zero, &done); | |
153 // Check if the object has been loaded. | 152 // Check if the object has been loaded. |
154 __ movq(kScratchRegister, FieldOperand(value, JSFunction::kMapOffset)); | 153 __ movq(kScratchRegister, FieldOperand(value, JSFunction::kMapOffset)); |
155 __ testb(FieldOperand(kScratchRegister, Map::kBitField2Offset), | 154 __ testb(FieldOperand(kScratchRegister, Map::kBitField2Offset), |
156 Immediate(1 << Map::kNeedsLoading)); | 155 Immediate(1 << Map::kNeedsLoading)); |
157 __ j(not_zero, miss); | 156 __ j(not_zero, miss); |
158 __ bind(&done); | 157 __ bind(&done); |
159 } | 158 } |
160 | 159 |
161 | 160 |
162 // One byte opcode for test eax,0xXXXXXXXX. | 161 // One byte opcode for test eax,0xXXXXXXXX. |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 // -- rsp[8] : name | 257 // -- rsp[8] : name |
259 // -- rsp[16] : receiver | 258 // -- rsp[16] : receiver |
260 // ----------------------------------- | 259 // ----------------------------------- |
261 Label slow, fast, check_string, index_int, index_string; | 260 Label slow, fast, check_string, index_int, index_string; |
262 | 261 |
263 // Load name and receiver. | 262 // Load name and receiver. |
264 __ movq(rax, Operand(rsp, kPointerSize)); | 263 __ movq(rax, Operand(rsp, kPointerSize)); |
265 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); | 264 __ movq(rcx, Operand(rsp, 2 * kPointerSize)); |
266 | 265 |
267 // Check that the object isn't a smi. | 266 // Check that the object isn't a smi. |
268 __ testl(rcx, Immediate(kSmiTagMask)); | 267 __ JumpIfSmi(rcx, &slow); |
269 __ j(zero, &slow); | |
270 | 268 |
271 // Check that the object is some kind of JS object EXCEPT JS Value type. | 269 // Check that the object is some kind of JS object EXCEPT JS Value type. |
272 // In the case that the object is a value-wrapper object, | 270 // In the case that the object is a value-wrapper object, |
273 // we enter the runtime system to make sure that indexing | 271 // we enter the runtime system to make sure that indexing |
274 // into string objects work as intended. | 272 // into string objects work as intended. |
275 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); | 273 ASSERT(JS_OBJECT_TYPE > JS_VALUE_TYPE); |
276 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); | 274 __ CmpObjectType(rcx, JS_OBJECT_TYPE, rdx); |
277 __ j(below, &slow); | 275 __ j(below, &slow); |
278 // Check that the receiver does not require access checks. We need | 276 // Check that the receiver does not require access checks. We need |
279 // to check this explicitly since this generic stub does not perform | 277 // to check this explicitly since this generic stub does not perform |
280 // map checks. The map is already in rdx. | 278 // map checks. The map is already in rdx. |
281 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 279 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
282 Immediate(1 << Map::kIsAccessCheckNeeded)); | 280 Immediate(1 << Map::kIsAccessCheckNeeded)); |
283 __ j(not_zero, &slow); | 281 __ j(not_zero, &slow); |
284 | 282 |
285 // Check that the key is a smi. | 283 // Check that the key is a smi. |
286 __ testl(rax, Immediate(kSmiTagMask)); | 284 __ JumpIfNotSmi(rax, &check_string); |
287 __ j(not_zero, &check_string); | 285 __ SmiToInteger32(rax, rax); |
288 __ sarl(rax, Immediate(kSmiTagSize)); | |
289 // Get the elements array of the object. | 286 // Get the elements array of the object. |
290 __ bind(&index_int); | 287 __ bind(&index_int); |
291 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); | 288 __ movq(rcx, FieldOperand(rcx, JSObject::kElementsOffset)); |
292 // Check that the object is in fast mode (not dictionary). | 289 // Check that the object is in fast mode (not dictionary). |
293 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); | 290 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); |
294 __ j(not_equal, &slow); | 291 __ j(not_equal, &slow); |
295 // Check that the key (index) is within bounds. | 292 // Check that the key (index) is within bounds. |
296 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); | 293 __ cmpl(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); |
297 __ j(below, &fast); // Unsigned comparison rejects negative indices. | 294 __ j(below, &fast); // Unsigned comparison rejects negative indices. |
298 // Slow case: Load name and receiver from stack and jump to runtime. | 295 // Slow case: Load name and receiver from stack and jump to runtime. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 // -- rax : value | 400 // -- rax : value |
404 // -- rsp[0] : return address | 401 // -- rsp[0] : return address |
405 // -- rsp[8] : key | 402 // -- rsp[8] : key |
406 // -- rsp[16] : receiver | 403 // -- rsp[16] : receiver |
407 // ----------------------------------- | 404 // ----------------------------------- |
408 Label slow, fast, array, extra; | 405 Label slow, fast, array, extra; |
409 | 406 |
410 // Get the receiver from the stack. | 407 // Get the receiver from the stack. |
411 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key | 408 __ movq(rdx, Operand(rsp, 2 * kPointerSize)); // 2 ~ return address, key |
412 // Check that the object isn't a smi. | 409 // Check that the object isn't a smi. |
413 __ testl(rdx, Immediate(kSmiTagMask)); | 410 __ JumpIfSmi(rdx, &slow); |
414 __ j(zero, &slow); | |
415 // Get the map from the receiver. | 411 // Get the map from the receiver. |
416 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); | 412 __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); |
417 // Check that the receiver does not require access checks. We need | 413 // Check that the receiver does not require access checks. We need |
418 // to do this because this generic stub does not perform map checks. | 414 // to do this because this generic stub does not perform map checks. |
419 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), | 415 __ testb(FieldOperand(rcx, Map::kBitFieldOffset), |
420 Immediate(1 << Map::kIsAccessCheckNeeded)); | 416 Immediate(1 << Map::kIsAccessCheckNeeded)); |
421 __ j(not_zero, &slow); | 417 __ j(not_zero, &slow); |
422 // Get the key from the stack. | 418 // Get the key from the stack. |
423 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address | 419 __ movq(rbx, Operand(rsp, 1 * kPointerSize)); // 1 ~ return address |
424 // Check that the key is a smi. | 420 // Check that the key is a smi. |
425 __ testl(rbx, Immediate(kSmiTagMask)); | 421 __ JumpIfNotSmi(rbx, &slow); |
426 __ j(not_zero, &slow); | |
427 // If it is a smi, make sure it is zero-extended, so it can be | 422 // If it is a smi, make sure it is zero-extended, so it can be |
428 // used as an index in a memory operand. | 423 // used as an index in a memory operand. |
429 __ movl(rbx, rbx); // Clear the high bits of rbx. | 424 __ movl(rbx, rbx); // Clear the high bits of rbx. |
430 | 425 |
431 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); | 426 __ CmpInstanceType(rcx, JS_ARRAY_TYPE); |
432 __ j(equal, &array); | 427 __ j(equal, &array); |
433 // Check that the object is some kind of JS object. | 428 // Check that the object is some kind of JS object. |
434 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); | 429 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); |
435 __ j(below, &slow); | 430 __ j(below, &slow); |
436 | 431 |
437 // Object case: Check key against length in the elements array. | 432 // Object case: Check key against length in the elements array. |
438 // rax: value | 433 // rax: value |
439 // rdx: JSObject | 434 // rdx: JSObject |
440 // rbx: index (as a smi), zero-extended. | 435 // rbx: index (as a smi), zero-extended. |
441 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 436 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
442 // Check that the object is in fast mode (not dictionary). | 437 // Check that the object is in fast mode (not dictionary). |
443 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); | 438 __ Cmp(FieldOperand(rcx, HeapObject::kMapOffset), Factory::fixed_array_map()); |
444 __ j(not_equal, &slow); | 439 __ j(not_equal, &slow); |
445 // Untag the key (for checking against untagged length in the fixed array). | 440 // Untag the key (for checking against untagged length in the fixed array). |
446 __ movl(rdx, rbx); | 441 __ SmiToInteger32(rdx, rbx); |
447 __ sarl(rdx, Immediate(kSmiTagSize)); | |
448 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); | 442 __ cmpl(rdx, FieldOperand(rcx, Array::kLengthOffset)); |
449 // rax: value | 443 // rax: value |
450 // rcx: FixedArray | 444 // rcx: FixedArray |
451 // rbx: index (as a smi) | 445 // rbx: index (as a smi) |
452 __ j(below, &fast); | 446 __ j(below, &fast); |
453 | 447 |
454 | 448 |
455 // Slow case: Push extra copies of the arguments (3). | 449 // Slow case: Push extra copies of the arguments (3). |
456 __ bind(&slow); | 450 __ bind(&slow); |
457 __ pop(rcx); | 451 __ pop(rcx); |
458 __ push(Operand(rsp, 1 * kPointerSize)); | 452 __ push(Operand(rsp, 1 * kPointerSize)); |
459 __ push(Operand(rsp, 1 * kPointerSize)); | 453 __ push(Operand(rsp, 1 * kPointerSize)); |
460 __ push(rax); | 454 __ push(rax); |
461 __ push(rcx); | 455 __ push(rcx); |
462 // Do tail-call to runtime routine. | 456 // Do tail-call to runtime routine. |
463 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); | 457 __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1); |
464 | 458 |
465 | 459 |
466 // Extra capacity case: Check if there is extra capacity to | 460 // Extra capacity case: Check if there is extra capacity to |
467 // perform the store and update the length. Used for adding one | 461 // perform the store and update the length. Used for adding one |
468 // element to the array by writing to array[array.length]. | 462 // element to the array by writing to array[array.length]. |
469 __ bind(&extra); | 463 __ bind(&extra); |
470 // rax: value | 464 // rax: value |
471 // rdx: JSArray | 465 // rdx: JSArray |
472 // rcx: FixedArray | 466 // rcx: FixedArray |
473 // rbx: index (as a smi) | 467 // rbx: index (as a smi) |
474 // flags: compare (rbx, rdx.length()) | 468 // flags: compare (rbx, rdx.length()) |
475 __ j(not_equal, &slow); // do not leave holes in the array | 469 __ j(not_equal, &slow); // do not leave holes in the array |
476 __ sarl(rbx, Immediate(kSmiTagSize)); // untag | 470 __ SmiToInteger64(rbx, rbx); |
477 __ cmpl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); | 471 __ cmpl(rbx, FieldOperand(rcx, FixedArray::kLengthOffset)); |
478 __ j(above_equal, &slow); | 472 __ j(above_equal, &slow); |
479 // Restore tag and increment. | 473 // Increment and restore smi-tag. |
480 __ lea(rbx, Operand(rbx, rbx, times_1, 1 << kSmiTagSize)); | 474 __ Integer64AddToSmi(rbx, rbx, 1); |
481 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rbx); | 475 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rbx); |
482 __ subl(rbx, Immediate(1 << kSmiTagSize)); // decrement rbx again | 476 __ SmiSubConstant(rbx, rbx, 1, NULL); |
483 __ jmp(&fast); | 477 __ jmp(&fast); |
484 | 478 |
485 | 479 |
486 // Array case: Get the length and the elements array from the JS | 480 // Array case: Get the length and the elements array from the JS |
487 // array. Check that the array is in fast mode; if it is the | 481 // array. Check that the array is in fast mode; if it is the |
488 // length is always a smi. | 482 // length is always a smi. |
489 __ bind(&array); | 483 __ bind(&array); |
490 // rax: value | 484 // rax: value |
491 // rdx: JSArray | 485 // rdx: JSArray |
492 // rbx: index (as a smi) | 486 // rbx: index (as a smi) |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 __ movq(rbx, f); | 531 __ movq(rbx, f); |
538 __ CallStub(&stub); | 532 __ CallStub(&stub); |
539 | 533 |
540 // Move result to rdi and exit the internal frame. | 534 // Move result to rdi and exit the internal frame. |
541 __ movq(rdi, rax); | 535 __ movq(rdi, rax); |
542 __ LeaveInternalFrame(); | 536 __ LeaveInternalFrame(); |
543 | 537 |
544 // Check if the receiver is a global object of some sort. | 538 // Check if the receiver is a global object of some sort. |
545 Label invoke, global; | 539 Label invoke, global; |
546 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver | 540 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); // receiver |
547 __ testl(rdx, Immediate(kSmiTagMask)); | 541 __ JumpIfSmi(rdx, &invoke); |
548 __ j(zero, &invoke); | |
549 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); | 542 __ CmpObjectType(rdx, JS_GLOBAL_OBJECT_TYPE, rcx); |
550 __ j(equal, &global); | 543 __ j(equal, &global); |
551 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); | 544 __ CmpInstanceType(rcx, JS_BUILTINS_OBJECT_TYPE); |
552 __ j(not_equal, &invoke); | 545 __ j(not_equal, &invoke); |
553 | 546 |
554 // Patch the receiver on the stack. | 547 // Patch the receiver on the stack. |
555 __ bind(&global); | 548 __ bind(&global); |
556 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); | 549 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); |
557 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); | 550 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); |
558 | 551 |
(...skipping 28 matching lines...) Expand all Loading... |
587 Code::Flags flags = | 580 Code::Flags flags = |
588 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); | 581 Code::ComputeFlags(Code::CALL_IC, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc); |
589 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax); | 582 StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax); |
590 | 583 |
591 // If the stub cache probing failed, the receiver might be a value. | 584 // If the stub cache probing failed, the receiver might be a value. |
592 // For value objects, we use the map of the prototype objects for | 585 // For value objects, we use the map of the prototype objects for |
593 // the corresponding JSValue for the cache and that is what we need | 586 // the corresponding JSValue for the cache and that is what we need |
594 // to probe. | 587 // to probe. |
595 // | 588 // |
596 // Check for number. | 589 // Check for number. |
597 __ testl(rdx, Immediate(kSmiTagMask)); | 590 __ JumpIfSmi(rdx, &number); |
598 __ j(zero, &number); | |
599 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rbx); | 591 __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rbx); |
600 __ j(not_equal, &non_number); | 592 __ j(not_equal, &non_number); |
601 __ bind(&number); | 593 __ bind(&number); |
602 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 594 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
603 masm, Context::NUMBER_FUNCTION_INDEX, rdx); | 595 masm, Context::NUMBER_FUNCTION_INDEX, rdx); |
604 __ jmp(&probe); | 596 __ jmp(&probe); |
605 | 597 |
606 // Check for string. | 598 // Check for string. |
607 __ bind(&non_number); | 599 __ bind(&non_number); |
608 __ CmpInstanceType(rbx, FIRST_NONSTRING_TYPE); | 600 __ CmpInstanceType(rbx, FIRST_NONSTRING_TYPE); |
(...skipping 24 matching lines...) Expand all Loading... |
633 | 625 |
634 static void GenerateNormalHelper(MacroAssembler* masm, | 626 static void GenerateNormalHelper(MacroAssembler* masm, |
635 int argc, | 627 int argc, |
636 bool is_global_object, | 628 bool is_global_object, |
637 Label* miss) { | 629 Label* miss) { |
638 // Search dictionary - put result in register edx. | 630 // Search dictionary - put result in register edx. |
639 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx); | 631 GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx); |
640 | 632 |
641 // Move the result to register rdi and check that it isn't a smi. | 633 // Move the result to register rdi and check that it isn't a smi. |
642 __ movq(rdi, rdx); | 634 __ movq(rdi, rdx); |
643 __ testl(rdx, Immediate(kSmiTagMask)); | 635 __ JumpIfSmi(rdx, miss); |
644 __ j(zero, miss); | |
645 | 636 |
646 // Check that the value is a JavaScript function. | 637 // Check that the value is a JavaScript function. |
647 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); | 638 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rdx); |
648 __ j(not_equal, miss); | 639 __ j(not_equal, miss); |
649 // Check that the function has been loaded. | 640 // Check that the function has been loaded. |
650 __ testb(FieldOperand(rdx, Map::kBitField2Offset), | 641 __ testb(FieldOperand(rdx, Map::kBitField2Offset), |
651 Immediate(1 << Map::kNeedsLoading)); | 642 Immediate(1 << Map::kNeedsLoading)); |
652 __ j(not_zero, miss); | 643 __ j(not_zero, miss); |
653 | 644 |
654 // Patch the receiver with the global proxy if necessary. | 645 // Patch the receiver with the global proxy if necessary. |
(...skipping 21 matching lines...) Expand all Loading... |
676 // ----------------------------------- | 667 // ----------------------------------- |
677 | 668 |
678 Label miss, global_object, non_global_object; | 669 Label miss, global_object, non_global_object; |
679 | 670 |
680 // Get the receiver of the function from the stack. | 671 // Get the receiver of the function from the stack. |
681 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); | 672 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
682 // Get the name of the function from the stack. | 673 // Get the name of the function from the stack. |
683 __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize)); | 674 __ movq(rcx, Operand(rsp, (argc + 2) * kPointerSize)); |
684 | 675 |
685 // Check that the receiver isn't a smi. | 676 // Check that the receiver isn't a smi. |
686 __ testl(rdx, Immediate(kSmiTagMask)); | 677 __ JumpIfSmi(rdx, &miss); |
687 __ j(zero, &miss); | |
688 | 678 |
689 // Check that the receiver is a valid JS object. | 679 // Check that the receiver is a valid JS object. |
690 // Because there are so many map checks and type checks, do not | 680 // Because there are so many map checks and type checks, do not |
691 // use CmpObjectType, but load map and type into registers. | 681 // use CmpObjectType, but load map and type into registers. |
692 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); | 682 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); |
693 __ movb(rax, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 683 __ movb(rax, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
694 __ cmpb(rax, Immediate(FIRST_JS_OBJECT_TYPE)); | 684 __ cmpb(rax, Immediate(FIRST_JS_OBJECT_TYPE)); |
695 __ j(below, &miss); | 685 __ j(below, &miss); |
696 | 686 |
697 // If this assert fails, we have to check upper bound too. | 687 // If this assert fails, we have to check upper bound too. |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
837 // -- rcx : name | 827 // -- rcx : name |
838 // -- rsp[0] : return address | 828 // -- rsp[0] : return address |
839 // -- rsp[8] : receiver | 829 // -- rsp[8] : receiver |
840 // ----------------------------------- | 830 // ----------------------------------- |
841 | 831 |
842 Label miss, probe, global; | 832 Label miss, probe, global; |
843 | 833 |
844 __ movq(rax, Operand(rsp, kPointerSize)); | 834 __ movq(rax, Operand(rsp, kPointerSize)); |
845 | 835 |
846 // Check that the receiver isn't a smi. | 836 // Check that the receiver isn't a smi. |
847 __ testl(rax, Immediate(kSmiTagMask)); | 837 __ JumpIfSmi(rax, &miss); |
848 __ j(zero, &miss); | |
849 | 838 |
850 // Check that the receiver is a valid JS object. | 839 // Check that the receiver is a valid JS object. |
851 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); | 840 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); |
852 __ j(below, &miss); | 841 __ j(below, &miss); |
853 | 842 |
854 // If this assert fails, we have to check upper bound too. | 843 // If this assert fails, we have to check upper bound too. |
855 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 844 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
856 | 845 |
857 // Check for access to global object (unlikely). | 846 // Check for access to global object (unlikely). |
858 __ CmpInstanceType(rbx, JS_GLOBAL_PROXY_TYPE); | 847 __ CmpInstanceType(rbx, JS_GLOBAL_PROXY_TYPE); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
979 | 968 |
980 // Cache miss: Jump to runtime. | 969 // Cache miss: Jump to runtime. |
981 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); | 970 Generate(masm, ExternalReference(IC_Utility(kStoreIC_Miss))); |
982 } | 971 } |
983 | 972 |
984 | 973 |
985 #undef __ | 974 #undef __ |
986 | 975 |
987 | 976 |
988 } } // namespace v8::internal | 977 } } // namespace v8::internal |
OLD | NEW |