| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 26 matching lines...) Expand all Loading... |
| 37 | 37 |
| 38 // ---------------------------------------------------------------------------- | 38 // ---------------------------------------------------------------------------- |
| 39 // Static IC stub generators. | 39 // Static IC stub generators. |
| 40 // | 40 // |
| 41 | 41 |
| 42 #define __ masm-> | 42 #define __ masm-> |
| 43 | 43 |
| 44 | 44 |
| 45 // Helper function used from LoadIC/CallIC GenerateNormal. | 45 // Helper function used from LoadIC/CallIC GenerateNormal. |
| 46 static void GenerateDictionaryLoad(MacroAssembler* masm, | 46 static void GenerateDictionaryLoad(MacroAssembler* masm, |
| 47 Label* done_label, | 47 Label* miss, |
| 48 Label* miss_label, | |
| 49 Register t0, | 48 Register t0, |
| 50 Register t1) { | 49 Register t1) { |
| 51 // Register use: | 50 // Register use: |
| 52 // | 51 // |
| 53 // t0 - used to hold the property dictionary. | 52 // t0 - used to hold the property dictionary. |
| 54 // | 53 // |
| 55 // t1 - initially the receiver | 54 // t1 - initially the receiver |
| 56 // - used for the index into the property dictionary | 55 // - used for the index into the property dictionary |
| 57 // - holds the result on exit. | 56 // - holds the result on exit. |
| 58 // | 57 // |
| 59 // r3 - used as temporary and to hold the capacity of the property | 58 // r3 - used as temporary and to hold the capacity of the property |
| 60 // dictionary. | 59 // dictionary. |
| 61 // | 60 // |
| 62 // r2 - holds the name of the property and is unchanges. | 61 // r2 - holds the name of the property and is unchanges. |
| 63 | 62 |
| 63 Label done; |
| 64 |
| 64 // Check for the absence of an interceptor. | 65 // Check for the absence of an interceptor. |
| 65 // Load the map into t0. | 66 // Load the map into t0. |
| 66 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); | 67 __ ldr(t0, FieldMemOperand(t1, JSObject::kMapOffset)); |
| 67 // Test the has_named_interceptor bit in the map. | 68 // Test the has_named_interceptor bit in the map. |
| 68 __ ldr(t0, FieldMemOperand(t1, Map::kInstanceAttributesOffset)); | 69 __ ldr(t0, FieldMemOperand(t1, Map::kInstanceAttributesOffset)); |
| 69 __ tst(t0, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8)))); | 70 __ tst(t0, Operand(1 << (Map::kHasNamedInterceptor + (3 * 8)))); |
| 70 // Jump to miss if the interceptor bit is set. | 71 // Jump to miss if the interceptor bit is set. |
| 71 __ b(ne, miss_label); | 72 __ b(ne, miss); |
| 72 | 73 |
| 73 | 74 |
| 74 // Check that the properties array is a dictionary. | 75 // Check that the properties array is a dictionary. |
| 75 __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset)); | 76 __ ldr(t0, FieldMemOperand(t1, JSObject::kPropertiesOffset)); |
| 76 __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset)); | 77 __ ldr(r3, FieldMemOperand(t0, HeapObject::kMapOffset)); |
| 77 __ cmp(r3, Operand(Factory::hash_table_map())); | 78 __ cmp(r3, Operand(Factory::hash_table_map())); |
| 78 __ b(ne, miss_label); | 79 __ b(ne, miss); |
| 79 | 80 |
| 80 // Compute the capacity mask. | 81 // Compute the capacity mask. |
| 81 const int kCapacityOffset = | 82 const int kCapacityOffset = |
| 82 Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize; | 83 Array::kHeaderSize + Dictionary::kCapacityIndex * kPointerSize; |
| 83 __ ldr(r3, FieldMemOperand(t0, kCapacityOffset)); | 84 __ ldr(r3, FieldMemOperand(t0, kCapacityOffset)); |
| 84 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); // convert smi to int | 85 __ mov(r3, Operand(r3, ASR, kSmiTagSize)); // convert smi to int |
| 85 __ sub(r3, r3, Operand(1)); | 86 __ sub(r3, r3, Operand(1)); |
| 86 | 87 |
| 87 const int kElementsStartOffset = | 88 const int kElementsStartOffset = |
| 88 Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize; | 89 Array::kHeaderSize + Dictionary::kElementsStartIndex * kPointerSize; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 100 | 101 |
| 101 // Scale the index by multiplying by the element size. | 102 // Scale the index by multiplying by the element size. |
| 102 ASSERT(Dictionary::kElementSize == 3); | 103 ASSERT(Dictionary::kElementSize == 3); |
| 103 __ add(t1, t1, Operand(t1, LSL, 1)); // t1 = t1 * 3 | 104 __ add(t1, t1, Operand(t1, LSL, 1)); // t1 = t1 * 3 |
| 104 | 105 |
| 105 // Check if the key is identical to the name. | 106 // Check if the key is identical to the name. |
| 106 __ add(t1, t0, Operand(t1, LSL, 2)); | 107 __ add(t1, t0, Operand(t1, LSL, 2)); |
| 107 __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset)); | 108 __ ldr(ip, FieldMemOperand(t1, kElementsStartOffset)); |
| 108 __ cmp(r2, Operand(ip)); | 109 __ cmp(r2, Operand(ip)); |
| 109 if (i != kProbes - 1) { | 110 if (i != kProbes - 1) { |
| 110 __ b(eq, done_label); | 111 __ b(eq, &done); |
| 111 } else { | 112 } else { |
| 112 __ b(ne, miss_label); | 113 __ b(ne, miss); |
| 113 } | 114 } |
| 114 } | 115 } |
| 115 | 116 |
| 116 // Check that the value is a normal property. | 117 // Check that the value is a normal property. |
| 117 __ bind(done_label); // t1 == t0 + 4*index | 118 __ bind(&done); // t1 == t0 + 4*index |
| 118 __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize)); | 119 __ ldr(r3, FieldMemOperand(t1, kElementsStartOffset + 2 * kPointerSize)); |
| 119 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); | 120 __ tst(r3, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
| 120 __ b(ne, miss_label); | 121 __ b(ne, miss); |
| 121 | 122 |
| 122 // Get the value at the masked, scaled index and return. | 123 // Get the value at the masked, scaled index and return. |
| 123 __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize)); | 124 __ ldr(t1, FieldMemOperand(t1, kElementsStartOffset + 1 * kPointerSize)); |
| 124 } | 125 } |
| 125 | 126 |
| 126 | 127 |
| 127 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 128 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 128 // ----------- S t a t e ------------- | 129 // ----------- S t a t e ------------- |
| 129 // -- r2 : name | 130 // -- r2 : name |
| 130 // -- lr : return address | 131 // -- lr : return address |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 333 // Probe the stub cache for the value object. | 334 // Probe the stub cache for the value object. |
| 334 __ bind(&probe); | 335 __ bind(&probe); |
| 335 StubCache::GenerateProbe(masm, flags, r1, r2, r3); | 336 StubCache::GenerateProbe(masm, flags, r1, r2, r3); |
| 336 | 337 |
| 337 // Cache miss: Jump to runtime. | 338 // Cache miss: Jump to runtime. |
| 338 __ bind(&miss); | 339 __ bind(&miss); |
| 339 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); | 340 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); |
| 340 } | 341 } |
| 341 | 342 |
| 342 | 343 |
| 344 static void GenerateNormalHelper(MacroAssembler* masm, |
| 345 int argc, |
| 346 bool is_global_object, |
| 347 Label* miss) { |
| 348 // Search dictionary - put result in register r1. |
| 349 GenerateDictionaryLoad(masm, miss, r0, r1); |
| 350 |
| 351 // Check that the value isn't a smi. |
| 352 __ tst(r1, Operand(kSmiTagMask)); |
| 353 __ b(eq, miss); |
| 354 |
| 355 // Check that the value is a JSFunction. |
| 356 __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 357 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 358 __ cmp(r0, Operand(JS_FUNCTION_TYPE)); |
| 359 __ b(ne, miss); |
| 360 |
| 361 // Patch the receiver with the global proxy if necessary. |
| 362 if (is_global_object) { |
| 363 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); |
| 364 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); |
| 365 __ str(r2, MemOperand(sp, argc * kPointerSize)); |
| 366 } |
| 367 |
| 368 // Invoke the function. |
| 369 ParameterCount actual(argc); |
| 370 __ InvokeFunction(r1, actual, JUMP_FUNCTION); |
| 371 } |
| 372 |
| 373 |
| 343 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 374 void CallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
| 344 // ----------- S t a t e ------------- | 375 // ----------- S t a t e ------------- |
| 345 // -- lr: return address | 376 // -- lr: return address |
| 346 // ----------------------------------- | 377 // ----------------------------------- |
| 347 | 378 |
| 348 Label miss, probe, done, global; | 379 Label miss, global_object, non_global_object; |
| 349 | 380 |
| 350 // Get the receiver of the function from the stack into r1. | 381 // Get the receiver of the function from the stack into r1. |
| 351 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); | 382 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); |
| 352 // Get the name of the function from the stack; 1 ~ receiver. | 383 // Get the name of the function from the stack; 1 ~ receiver. |
| 353 __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize)); | 384 __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize)); |
| 354 | 385 |
| 355 // Check that the receiver isn't a smi. | 386 // Check that the receiver isn't a smi. |
| 356 __ tst(r1, Operand(kSmiTagMask)); | 387 __ tst(r1, Operand(kSmiTagMask)); |
| 357 __ b(eq, &miss); | 388 __ b(eq, &miss); |
| 358 | 389 |
| 359 // Check that the receiver is a valid JS object. | 390 // Check that the receiver is a valid JS object. |
| 360 __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset)); | 391 __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset)); |
| 361 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | 392 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); |
| 362 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE)); | 393 __ cmp(r0, Operand(FIRST_JS_OBJECT_TYPE)); |
| 363 __ b(lt, &miss); | 394 __ b(lt, &miss); |
| 364 | 395 |
| 365 // If this assert fails, we have to check upper bound too. | 396 // If this assert fails, we have to check upper bound too. |
| 366 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 397 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 367 | 398 |
| 368 // Check for access to global proxy. | 399 // Check for access to global object. |
| 400 __ cmp(r0, Operand(JS_GLOBAL_OBJECT_TYPE)); |
| 401 __ b(eq, &global_object); |
| 402 __ cmp(r0, Operand(JS_BUILTINS_OBJECT_TYPE)); |
| 403 __ b(ne, &non_global_object); |
| 404 |
| 405 // Accessing global object: Load and invoke. |
| 406 __ bind(&global_object); |
| 407 GenerateNormalHelper(masm, argc, true, &miss); |
| 408 |
| 409 // Accessing non-global object: Check for access to global proxy. |
| 410 Label global_proxy, invoke; |
| 411 __ bind(&non_global_object); |
| 369 __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE)); | 412 __ cmp(r0, Operand(JS_GLOBAL_PROXY_TYPE)); |
| 370 __ b(eq, &global); | 413 __ b(eq, &global_proxy); |
| 371 | 414 __ bind(&invoke); |
| 372 // Search the dictionary placing the result in r1. | 415 GenerateNormalHelper(masm, argc, false, &miss); |
| 373 __ bind(&probe); | |
| 374 GenerateDictionaryLoad(masm, &done, &miss, r0, r1); | |
| 375 | |
| 376 // Check that the value isn't a smi. | |
| 377 __ tst(r1, Operand(kSmiTagMask)); | |
| 378 __ b(eq, &miss); | |
| 379 | |
| 380 // Check that the value is a JSFunction. | |
| 381 __ ldr(r0, FieldMemOperand(r1, HeapObject::kMapOffset)); | |
| 382 __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); | |
| 383 __ cmp(r0, Operand(JS_FUNCTION_TYPE)); | |
| 384 __ b(ne, &miss); | |
| 385 | |
| 386 // TODO(120): Check for access to global object. Needs patching of | |
| 387 // receiver but no security check. | |
| 388 | |
| 389 // Invoke the function. | |
| 390 ParameterCount actual(argc); | |
| 391 __ InvokeFunction(r1, actual, JUMP_FUNCTION); | |
| 392 | 416 |
| 393 // Global object access: Check access rights. | 417 // Global object access: Check access rights. |
| 394 __ bind(&global); | 418 __ bind(&global_proxy); |
| 395 __ CheckAccessGlobalProxy(r1, r0, &miss); | 419 __ CheckAccessGlobalProxy(r1, r0, &miss); |
| 396 __ b(&probe); | 420 __ b(&invoke); |
| 397 | 421 |
| 398 // Cache miss: Jump to runtime. | 422 // Cache miss: Jump to runtime. |
| 399 __ bind(&miss); | 423 __ bind(&miss); |
| 400 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); | 424 Generate(masm, argc, ExternalReference(IC_Utility(kCallIC_Miss))); |
| 401 } | 425 } |
| 402 | 426 |
| 403 | 427 |
| 404 void CallIC::Generate(MacroAssembler* masm, | 428 void CallIC::Generate(MacroAssembler* masm, |
| 405 int argc, | 429 int argc, |
| 406 const ExternalReference& f) { | 430 const ExternalReference& f) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 422 __ mov(r0, Operand(2)); | 446 __ mov(r0, Operand(2)); |
| 423 __ mov(r1, Operand(f)); | 447 __ mov(r1, Operand(f)); |
| 424 | 448 |
| 425 CEntryStub stub; | 449 CEntryStub stub; |
| 426 __ CallStub(&stub); | 450 __ CallStub(&stub); |
| 427 | 451 |
| 428 // Move result to r1 and leave the internal frame. | 452 // Move result to r1 and leave the internal frame. |
| 429 __ mov(r1, Operand(r0)); | 453 __ mov(r1, Operand(r0)); |
| 430 __ LeaveInternalFrame(); | 454 __ LeaveInternalFrame(); |
| 431 | 455 |
| 432 // TODO(120): Check for access to to global object. Needs patching | 456 // Check if the receiver is a global object of some sort. |
| 433 // of receiver but no security check. | 457 Label invoke, global; |
| 458 __ ldr(r2, MemOperand(sp, argc * kPointerSize)); // receiver |
| 459 __ tst(r2, Operand(kSmiTagMask)); |
| 460 __ b(eq, &invoke); |
| 461 __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset)); |
| 462 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset)); |
| 463 __ cmp(r3, Operand(JS_GLOBAL_OBJECT_TYPE)); |
| 464 __ b(eq, &global); |
| 465 __ cmp(r3, Operand(JS_BUILTINS_OBJECT_TYPE)); |
| 466 __ b(ne, &invoke); |
| 467 |
| 468 // Patch the receiver on the stack. |
| 469 __ bind(&global); |
| 470 __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset)); |
| 471 __ str(r2, MemOperand(sp, argc * kPointerSize)); |
| 434 | 472 |
| 435 // Invoke the function. | 473 // Invoke the function. |
| 436 ParameterCount actual(argc); | 474 ParameterCount actual(argc); |
| 475 __ bind(&invoke); |
| 437 __ InvokeFunction(r1, actual, JUMP_FUNCTION); | 476 __ InvokeFunction(r1, actual, JUMP_FUNCTION); |
| 438 } | 477 } |
| 439 | 478 |
| 440 | 479 |
| 441 // Defined in ic.cc. | 480 // Defined in ic.cc. |
| 442 Object* LoadIC_Miss(Arguments args); | 481 Object* LoadIC_Miss(Arguments args); |
| 443 | 482 |
| 444 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { | 483 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { |
| 445 // ----------- S t a t e ------------- | 484 // ----------- S t a t e ------------- |
| 446 // -- r2 : name | 485 // -- r2 : name |
| (...skipping 11 matching lines...) Expand all Loading... |
| 458 } | 497 } |
| 459 | 498 |
| 460 | 499 |
| 461 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 500 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 462 // ----------- S t a t e ------------- | 501 // ----------- S t a t e ------------- |
| 463 // -- r2 : name | 502 // -- r2 : name |
| 464 // -- lr : return address | 503 // -- lr : return address |
| 465 // -- [sp] : receiver | 504 // -- [sp] : receiver |
| 466 // ----------------------------------- | 505 // ----------------------------------- |
| 467 | 506 |
| 468 Label miss, probe, done, global; | 507 Label miss, probe, global; |
| 469 | 508 |
| 470 __ ldr(r0, MemOperand(sp, 0)); | 509 __ ldr(r0, MemOperand(sp, 0)); |
| 471 // Check that the receiver isn't a smi. | 510 // Check that the receiver isn't a smi. |
| 472 __ tst(r0, Operand(kSmiTagMask)); | 511 __ tst(r0, Operand(kSmiTagMask)); |
| 473 __ b(eq, &miss); | 512 __ b(eq, &miss); |
| 474 | 513 |
| 475 // Check that the receiver is a valid JS object. | 514 // Check that the receiver is a valid JS object. |
| 476 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 515 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 477 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); | 516 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset)); |
| 478 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); | 517 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); |
| 479 __ b(lt, &miss); | 518 __ b(lt, &miss); |
| 480 // If this assert fails, we have to check upper bound too. | 519 // If this assert fails, we have to check upper bound too. |
| 481 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 520 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); |
| 482 | 521 |
| 483 // Check for access to global object (unlikely). | 522 // Check for access to global object (unlikely). |
| 484 __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE)); | 523 __ cmp(r1, Operand(JS_GLOBAL_PROXY_TYPE)); |
| 485 __ b(eq, &global); | 524 __ b(eq, &global); |
| 486 | 525 |
| 487 __ bind(&probe); | 526 __ bind(&probe); |
| 488 GenerateDictionaryLoad(masm, &done, &miss, r1, r0); | 527 GenerateDictionaryLoad(masm, &miss, r1, r0); |
| 489 __ Ret(); | 528 __ Ret(); |
| 490 | 529 |
| 491 // Global object access: Check access rights. | 530 // Global object access: Check access rights. |
| 492 __ bind(&global); | 531 __ bind(&global); |
| 493 __ CheckAccessGlobalProxy(r0, r1, &miss); | 532 __ CheckAccessGlobalProxy(r0, r1, &miss); |
| 494 __ b(&probe); | 533 __ b(&probe); |
| 495 | 534 |
| 496 // Cache miss: Restore receiver from stack and jump to runtime. | 535 // Cache miss: Restore receiver from stack and jump to runtime. |
| 497 __ bind(&miss); | 536 __ bind(&miss); |
| 498 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | 537 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 | 628 |
| 590 // Perform tail call to the entry. | 629 // Perform tail call to the entry. |
| 591 __ TailCallRuntime(f, 3); | 630 __ TailCallRuntime(f, 3); |
| 592 } | 631 } |
| 593 | 632 |
| 594 | 633 |
| 595 #undef __ | 634 #undef __ |
| 596 | 635 |
| 597 | 636 |
| 598 } } // namespace v8::internal | 637 } } // namespace v8::internal |
| OLD | NEW |