| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 Register r0, | 65 Register r0, |
| 66 Register r1, | 66 Register r1, |
| 67 Label* miss) { | 67 Label* miss) { |
| 68 // Register usage: | 68 // Register usage: |
| 69 // receiver: holds the receiver on entry and is unchanged. | 69 // receiver: holds the receiver on entry and is unchanged. |
| 70 // r0: used to hold receiver instance type. | 70 // r0: used to hold receiver instance type. |
| 71 // Holds the property dictionary on fall through. | 71 // Holds the property dictionary on fall through. |
| 72 // r1: used to hold receivers map. | 72 // r1: used to hold receivers map. |
| 73 | 73 |
| 74 // Check that the receiver isn't a smi. | 74 // Check that the receiver isn't a smi. |
| 75 __ test(receiver, Immediate(kSmiTagMask)); | 75 __ JumpIfSmi(receiver, miss); |
| 76 __ j(zero, miss); | |
| 77 | 76 |
| 78 // Check that the receiver is a valid JS object. | 77 // Check that the receiver is a valid JS object. |
| 79 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); | 78 __ mov(r1, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 80 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); | 79 __ movzx_b(r0, FieldOperand(r1, Map::kInstanceTypeOffset)); |
| 81 __ cmp(r0, FIRST_JS_OBJECT_TYPE); | 80 __ cmp(r0, FIRST_SPEC_OBJECT_TYPE); |
| 82 __ j(below, miss); | 81 __ j(below, miss); |
| 83 | 82 |
| 84 // If this assert fails, we have to check upper bound too. | 83 // If this assert fails, we have to check upper bound too. |
| 85 ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); | 84 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); |
| 86 | 85 |
| 87 GenerateGlobalInstanceTypeCheck(masm, r0, miss); | 86 GenerateGlobalInstanceTypeCheck(masm, r0, miss); |
| 88 | 87 |
| 89 // Check for non-global object that requires access check. | 88 // Check for non-global object that requires access check. |
| 90 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), | 89 __ test_b(FieldOperand(r1, Map::kBitFieldOffset), |
| 91 (1 << Map::kIsAccessCheckNeeded) | | 90 (1 << Map::kIsAccessCheckNeeded) | |
| 92 (1 << Map::kHasNamedInterceptor)); | 91 (1 << Map::kHasNamedInterceptor)); |
| 93 __ j(not_zero, miss); | 92 __ j(not_zero, miss); |
| 94 | 93 |
| 95 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); | 94 __ mov(r0, FieldOperand(receiver, JSObject::kPropertiesOffset)); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 const int kValueOffset = kElementsStartOffset + kPointerSize; | 209 const int kValueOffset = kElementsStartOffset + kPointerSize; |
| 211 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); | 210 __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); |
| 212 __ mov(Operand(r0, 0), value); | 211 __ mov(Operand(r0, 0), value); |
| 213 | 212 |
| 214 // Update write barrier. Make sure not to clobber the value. | 213 // Update write barrier. Make sure not to clobber the value. |
| 215 __ mov(r1, value); | 214 __ mov(r1, value); |
| 216 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs); | 215 __ RecordWrite(elements, r0, r1, kDontSaveFPRegs); |
| 217 } | 216 } |
| 218 | 217 |
| 219 | 218 |
| 220 static void GenerateNumberDictionaryLoad(MacroAssembler* masm, | |
| 221 Label* miss, | |
| 222 Register elements, | |
| 223 Register key, | |
| 224 Register r0, | |
| 225 Register r1, | |
| 226 Register r2, | |
| 227 Register result) { | |
| 228 // Register use: | |
| 229 // | |
| 230 // elements - holds the slow-case elements of the receiver and is unchanged. | |
| 231 // | |
| 232 // key - holds the smi key on entry and is unchanged. | |
| 233 // | |
| 234 // Scratch registers: | |
| 235 // | |
| 236 // r0 - holds the untagged key on entry and holds the hash once computed. | |
| 237 // | |
| 238 // r1 - used to hold the capacity mask of the dictionary | |
| 239 // | |
| 240 // r2 - used for the index into the dictionary. | |
| 241 // | |
| 242 // result - holds the result on exit if the load succeeds and we fall through. | |
| 243 | |
| 244 Label done; | |
| 245 | |
| 246 // Compute the hash code from the untagged key. This must be kept in sync | |
| 247 // with ComputeIntegerHash in utils.h. | |
| 248 // | |
| 249 // hash = ~hash + (hash << 15); | |
| 250 __ mov(r1, r0); | |
| 251 __ not_(r0); | |
| 252 __ shl(r1, 15); | |
| 253 __ add(r0, Operand(r1)); | |
| 254 // hash = hash ^ (hash >> 12); | |
| 255 __ mov(r1, r0); | |
| 256 __ shr(r1, 12); | |
| 257 __ xor_(r0, Operand(r1)); | |
| 258 // hash = hash + (hash << 2); | |
| 259 __ lea(r0, Operand(r0, r0, times_4, 0)); | |
| 260 // hash = hash ^ (hash >> 4); | |
| 261 __ mov(r1, r0); | |
| 262 __ shr(r1, 4); | |
| 263 __ xor_(r0, Operand(r1)); | |
| 264 // hash = hash * 2057; | |
| 265 __ imul(r0, r0, 2057); | |
| 266 // hash = hash ^ (hash >> 16); | |
| 267 __ mov(r1, r0); | |
| 268 __ shr(r1, 16); | |
| 269 __ xor_(r0, Operand(r1)); | |
| 270 | |
| 271 // Compute capacity mask. | |
| 272 __ mov(r1, FieldOperand(elements, NumberDictionary::kCapacityOffset)); | |
| 273 __ shr(r1, kSmiTagSize); // convert smi to int | |
| 274 __ dec(r1); | |
| 275 | |
| 276 // Generate an unrolled loop that performs a few probes before giving up. | |
| 277 const int kProbes = 4; | |
| 278 for (int i = 0; i < kProbes; i++) { | |
| 279 // Use r2 for index calculations and keep the hash intact in r0. | |
| 280 __ mov(r2, r0); | |
| 281 // Compute the masked index: (hash + i + i * i) & mask. | |
| 282 if (i > 0) { | |
| 283 __ add(Operand(r2), Immediate(NumberDictionary::GetProbeOffset(i))); | |
| 284 } | |
| 285 __ and_(r2, Operand(r1)); | |
| 286 | |
| 287 // Scale the index by multiplying by the entry size. | |
| 288 ASSERT(NumberDictionary::kEntrySize == 3); | |
| 289 __ lea(r2, Operand(r2, r2, times_2, 0)); // r2 = r2 * 3 | |
| 290 | |
| 291 // Check if the key matches. | |
| 292 __ cmp(key, FieldOperand(elements, | |
| 293 r2, | |
| 294 times_pointer_size, | |
| 295 NumberDictionary::kElementsStartOffset)); | |
| 296 if (i != (kProbes - 1)) { | |
| 297 __ j(equal, &done); | |
| 298 } else { | |
| 299 __ j(not_equal, miss); | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 __ bind(&done); | |
| 304 // Check that the value is a normal propety. | |
| 305 const int kDetailsOffset = | |
| 306 NumberDictionary::kElementsStartOffset + 2 * kPointerSize; | |
| 307 ASSERT_EQ(NORMAL, 0); | |
| 308 __ test(FieldOperand(elements, r2, times_pointer_size, kDetailsOffset), | |
| 309 Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); | |
| 310 __ j(not_zero, miss); | |
| 311 | |
| 312 // Get the value at the masked, scaled index. | |
| 313 const int kValueOffset = | |
| 314 NumberDictionary::kElementsStartOffset + kPointerSize; | |
| 315 __ mov(result, FieldOperand(elements, r2, times_pointer_size, kValueOffset)); | |
| 316 } | |
| 317 | |
| 318 | |
| 319 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { | 219 void LoadIC::GenerateArrayLength(MacroAssembler* masm) { |
| 320 // ----------- S t a t e ------------- | 220 // ----------- S t a t e ------------- |
| 321 // -- eax : receiver | 221 // -- eax : receiver |
| 322 // -- ecx : name | 222 // -- ecx : name |
| 323 // -- esp[0] : return address | 223 // -- esp[0] : return address |
| 324 // ----------------------------------- | 224 // ----------------------------------- |
| 325 Label miss; | 225 Label miss; |
| 326 | 226 |
| 327 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); | 227 StubCompiler::GenerateLoadArrayLength(masm, eax, edx, &miss); |
| 328 __ bind(&miss); | 228 __ bind(&miss); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 Register receiver, | 266 Register receiver, |
| 367 Register map, | 267 Register map, |
| 368 int interceptor_bit, | 268 int interceptor_bit, |
| 369 Label* slow) { | 269 Label* slow) { |
| 370 // Register use: | 270 // Register use: |
| 371 // receiver - holds the receiver and is unchanged. | 271 // receiver - holds the receiver and is unchanged. |
| 372 // Scratch registers: | 272 // Scratch registers: |
| 373 // map - used to hold the map of the receiver. | 273 // map - used to hold the map of the receiver. |
| 374 | 274 |
| 375 // Check that the object isn't a smi. | 275 // Check that the object isn't a smi. |
| 376 __ test(receiver, Immediate(kSmiTagMask)); | 276 __ JumpIfSmi(receiver, slow); |
| 377 __ j(zero, slow); | |
| 378 | 277 |
| 379 // Get the map of the receiver. | 278 // Get the map of the receiver. |
| 380 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); | 279 __ mov(map, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 381 | 280 |
| 382 // Check bit field. | 281 // Check bit field. |
| 383 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 282 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
| 384 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); | 283 (1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)); |
| 385 __ j(not_zero, slow); | 284 __ j(not_zero, slow); |
| 386 // Check that the object is some kind of JS object EXCEPT JS Value type. | 285 // Check that the object is some kind of JS object EXCEPT JS Value type. |
| 387 // In the case that the object is a value-wrapper object, | 286 // In the case that the object is a value-wrapper object, |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); | 357 __ test(hash, Immediate(String::kContainsCachedArrayIndexMask)); |
| 459 __ j(zero, index_string); | 358 __ j(zero, index_string); |
| 460 | 359 |
| 461 // Is the string a symbol? | 360 // Is the string a symbol? |
| 462 ASSERT(kSymbolTag != 0); | 361 ASSERT(kSymbolTag != 0); |
| 463 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); | 362 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsSymbolMask); |
| 464 __ j(zero, not_symbol); | 363 __ j(zero, not_symbol); |
| 465 } | 364 } |
| 466 | 365 |
| 467 | 366 |
| 367 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, |
| 368 Register object, |
| 369 Register key, |
| 370 Register scratch1, |
| 371 Register scratch2, |
| 372 Label* unmapped_case, |
| 373 Label* slow_case) { |
| 374 Heap* heap = masm->isolate()->heap(); |
| 375 Factory* factory = masm->isolate()->factory(); |
| 376 |
| 377 // Check that the receiver is a JSObject. Because of the elements |
| 378 // map check later, we do not need to check for interceptors or |
| 379 // whether it requires access checks. |
| 380 __ JumpIfSmi(object, slow_case); |
| 381 // Check that the object is some kind of JSObject. |
| 382 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); |
| 383 __ j(below, slow_case); |
| 384 |
| 385 // Check that the key is a positive smi. |
| 386 __ test(key, Immediate(0x8000001)); |
| 387 __ j(not_zero, slow_case); |
| 388 |
| 389 // Load the elements into scratch1 and check its map. |
| 390 Handle<Map> arguments_map(heap->non_strict_arguments_elements_map()); |
| 391 __ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset)); |
| 392 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); |
| 393 |
| 394 // Check if element is in the range of mapped arguments. If not, jump |
| 395 // to the unmapped lookup with the parameter map in scratch1. |
| 396 __ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); |
| 397 __ sub(Operand(scratch2), Immediate(Smi::FromInt(2))); |
| 398 __ cmp(key, Operand(scratch2)); |
| 399 __ j(greater_equal, unmapped_case); |
| 400 |
| 401 // Load element index and check whether it is the hole. |
| 402 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; |
| 403 __ mov(scratch2, FieldOperand(scratch1, |
| 404 key, |
| 405 times_half_pointer_size, |
| 406 kHeaderSize)); |
| 407 __ cmp(scratch2, factory->the_hole_value()); |
| 408 __ j(equal, unmapped_case); |
| 409 |
| 410 // Load value from context and return it. We can reuse scratch1 because |
| 411 // we do not jump to the unmapped lookup (which requires the parameter |
| 412 // map in scratch1). |
| 413 const int kContextOffset = FixedArray::kHeaderSize; |
| 414 __ mov(scratch1, FieldOperand(scratch1, kContextOffset)); |
| 415 return FieldOperand(scratch1, |
| 416 scratch2, |
| 417 times_half_pointer_size, |
| 418 Context::kHeaderSize); |
| 419 } |
| 420 |
| 421 |
| 422 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, |
| 423 Register key, |
| 424 Register parameter_map, |
| 425 Register scratch, |
| 426 Label* slow_case) { |
| 427 // Element is in arguments backing store, which is referenced by the |
| 428 // second element of the parameter_map. |
| 429 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; |
| 430 Register backing_store = parameter_map; |
| 431 __ mov(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); |
| 432 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); |
| 433 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); |
| 434 __ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); |
| 435 __ cmp(key, Operand(scratch)); |
| 436 __ j(greater_equal, slow_case); |
| 437 return FieldOperand(backing_store, |
| 438 key, |
| 439 times_half_pointer_size, |
| 440 FixedArray::kHeaderSize); |
| 441 } |
| 442 |
| 443 |
| 468 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { | 444 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { |
| 469 // ----------- S t a t e ------------- | 445 // ----------- S t a t e ------------- |
| 470 // -- eax : key | 446 // -- eax : key |
| 471 // -- edx : receiver | 447 // -- edx : receiver |
| 472 // -- esp[0] : return address | 448 // -- esp[0] : return address |
| 473 // ----------------------------------- | 449 // ----------------------------------- |
| 474 Label slow, check_string, index_smi, index_string, property_array_property; | 450 Label slow, check_string, index_smi, index_string, property_array_property; |
| 475 Label probe_dictionary, check_number_dictionary; | 451 Label probe_dictionary, check_number_dictionary; |
| 476 | 452 |
| 477 // Check that the key is a smi. | 453 // Check that the key is a smi. |
| 478 __ test(eax, Immediate(kSmiTagMask)); | 454 __ JumpIfNotSmi(eax, &check_string); |
| 479 __ j(not_zero, &check_string); | |
| 480 __ bind(&index_smi); | 455 __ bind(&index_smi); |
| 481 // Now the key is known to be a smi. This place is also jumped to from | 456 // Now the key is known to be a smi. This place is also jumped to from |
| 482 // where a numeric string is converted to a smi. | 457 // where a numeric string is converted to a smi. |
| 483 | 458 |
| 484 GenerateKeyedLoadReceiverCheck( | 459 GenerateKeyedLoadReceiverCheck( |
| 485 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); | 460 masm, edx, ecx, Map::kHasIndexedInterceptor, &slow); |
| 486 | 461 |
| 487 // Check the "has fast elements" bit in the receiver's map which is | 462 // Check the receiver's map to see if it has fast elements. |
| 488 // now in ecx. | 463 __ CheckFastElements(ecx, &check_number_dictionary); |
| 489 __ test_b(FieldOperand(ecx, Map::kBitField2Offset), | |
| 490 1 << Map::kHasFastElements); | |
| 491 __ j(zero, &check_number_dictionary); | |
| 492 | 464 |
| 493 GenerateFastArrayLoad(masm, | 465 GenerateFastArrayLoad(masm, |
| 494 edx, | 466 edx, |
| 495 eax, | 467 eax, |
| 496 ecx, | 468 ecx, |
| 497 eax, | 469 eax, |
| 498 NULL, | 470 NULL, |
| 499 &slow); | 471 &slow); |
| 500 Isolate* isolate = masm->isolate(); | 472 Isolate* isolate = masm->isolate(); |
| 501 Counters* counters = isolate->counters(); | 473 Counters* counters = isolate->counters(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 513 // eax: key | 485 // eax: key |
| 514 // ecx: elements | 486 // ecx: elements |
| 515 __ CheckMap(ecx, | 487 __ CheckMap(ecx, |
| 516 isolate->factory()->hash_table_map(), | 488 isolate->factory()->hash_table_map(), |
| 517 &slow, | 489 &slow, |
| 518 DONT_DO_SMI_CHECK); | 490 DONT_DO_SMI_CHECK); |
| 519 Label slow_pop_receiver; | 491 Label slow_pop_receiver; |
| 520 // Push receiver on the stack to free up a register for the dictionary | 492 // Push receiver on the stack to free up a register for the dictionary |
| 521 // probing. | 493 // probing. |
| 522 __ push(edx); | 494 __ push(edx); |
| 523 GenerateNumberDictionaryLoad(masm, | 495 __ LoadFromNumberDictionary(&slow_pop_receiver, |
| 524 &slow_pop_receiver, | 496 ecx, |
| 525 ecx, | 497 eax, |
| 526 eax, | 498 ebx, |
| 527 ebx, | 499 edx, |
| 528 edx, | 500 edi, |
| 529 edi, | 501 eax); |
| 530 eax); | |
| 531 // Pop receiver before returning. | 502 // Pop receiver before returning. |
| 532 __ pop(edx); | 503 __ pop(edx); |
| 533 __ ret(0); | 504 __ ret(0); |
| 534 | 505 |
| 535 __ bind(&slow_pop_receiver); | 506 __ bind(&slow_pop_receiver); |
| 536 // Pop the receiver from the stack and jump to runtime. | 507 // Pop the receiver from the stack and jump to runtime. |
| 537 __ pop(edx); | 508 __ pop(edx); |
| 538 | 509 |
| 539 __ bind(&slow); | 510 __ bind(&slow); |
| 540 // Slow case: jump to runtime. | 511 // Slow case: jump to runtime. |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 | 632 |
| 662 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { | 633 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) { |
| 663 // ----------- S t a t e ------------- | 634 // ----------- S t a t e ------------- |
| 664 // -- eax : key | 635 // -- eax : key |
| 665 // -- edx : receiver | 636 // -- edx : receiver |
| 666 // -- esp[0] : return address | 637 // -- esp[0] : return address |
| 667 // ----------------------------------- | 638 // ----------------------------------- |
| 668 Label slow; | 639 Label slow; |
| 669 | 640 |
| 670 // Check that the receiver isn't a smi. | 641 // Check that the receiver isn't a smi. |
| 671 __ test(edx, Immediate(kSmiTagMask)); | 642 __ JumpIfSmi(edx, &slow); |
| 672 __ j(zero, &slow); | |
| 673 | 643 |
| 674 // Check that the key is an array index, that is Uint32. | 644 // Check that the key is an array index, that is Uint32. |
| 675 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); | 645 __ test(eax, Immediate(kSmiTagMask | kSmiSignMask)); |
| 676 __ j(not_zero, &slow); | 646 __ j(not_zero, &slow); |
| 677 | 647 |
| 678 // Get the map of the receiver. | 648 // Get the map of the receiver. |
| 679 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); | 649 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 680 | 650 |
| 681 // Check that it has indexed interceptor and access checks | 651 // Check that it has indexed interceptor and access checks |
| 682 // are not enabled for this object. | 652 // are not enabled for this object. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 695 ExternalReference ref = | 665 ExternalReference ref = |
| 696 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), | 666 ExternalReference(IC_Utility(kKeyedLoadPropertyWithInterceptor), |
| 697 masm->isolate()); | 667 masm->isolate()); |
| 698 __ TailCallExternalReference(ref, 2, 1); | 668 __ TailCallExternalReference(ref, 2, 1); |
| 699 | 669 |
| 700 __ bind(&slow); | 670 __ bind(&slow); |
| 701 GenerateMiss(masm, false); | 671 GenerateMiss(masm, false); |
| 702 } | 672 } |
| 703 | 673 |
| 704 | 674 |
| 675 void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) { |
| 676 // ----------- S t a t e ------------- |
| 677 // -- eax : key |
| 678 // -- edx : receiver |
| 679 // -- esp[0] : return address |
| 680 // ----------------------------------- |
| 681 Label slow, notin; |
| 682 Factory* factory = masm->isolate()->factory(); |
| 683 Operand mapped_location = |
| 684 GenerateMappedArgumentsLookup(masm, edx, eax, ebx, ecx, ¬in, &slow); |
| 685 __ mov(eax, mapped_location); |
| 686 __ Ret(); |
| 687 __ bind(¬in); |
| 688 // The unmapped lookup expects that the parameter map is in ebx. |
| 689 Operand unmapped_location = |
| 690 GenerateUnmappedArgumentsLookup(masm, eax, ebx, ecx, &slow); |
| 691 __ cmp(unmapped_location, factory->the_hole_value()); |
| 692 __ j(equal, &slow); |
| 693 __ mov(eax, unmapped_location); |
| 694 __ Ret(); |
| 695 __ bind(&slow); |
| 696 GenerateMiss(masm, false); |
| 697 } |
| 698 |
| 699 |
| 700 void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) { |
| 701 // ----------- S t a t e ------------- |
| 702 // -- eax : value |
| 703 // -- ecx : key |
| 704 // -- edx : receiver |
| 705 // -- esp[0] : return address |
| 706 // ----------------------------------- |
| 707 Label slow, notin; |
| 708 Operand mapped_location = |
| 709 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, edi, ¬in, &slow); |
| 710 __ mov(mapped_location, eax); |
| 711 __ lea(ecx, mapped_location); |
| 712 __ mov(edx, eax); |
| 713 __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs); |
| 714 __ Ret(); |
| 715 __ bind(¬in); |
| 716 // The unmapped lookup expects that the parameter map is in ebx. |
| 717 Operand unmapped_location = |
| 718 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, edi, &slow); |
| 719 __ mov(unmapped_location, eax); |
| 720 __ lea(edi, unmapped_location); |
| 721 __ mov(edx, eax); |
| 722 __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs); |
| 723 __ Ret(); |
| 724 __ bind(&slow); |
| 725 GenerateMiss(masm, false); |
| 726 } |
| 727 |
| 728 |
| 705 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, | 729 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, |
| 706 StrictModeFlag strict_mode) { | 730 StrictModeFlag strict_mode) { |
| 707 // ----------- S t a t e ------------- | 731 // ----------- S t a t e ------------- |
| 708 // -- eax : value | 732 // -- eax : value |
| 709 // -- ecx : key | 733 // -- ecx : key |
| 710 // -- edx : receiver | 734 // -- edx : receiver |
| 711 // -- esp[0] : return address | 735 // -- esp[0] : return address |
| 712 // ----------------------------------- | 736 // ----------------------------------- |
| 713 Label slow, fast, array, extra; | 737 Label slow, fast, array, extra; |
| 714 | 738 |
| 715 // Check that the object isn't a smi. | 739 // Check that the object isn't a smi. |
| 716 __ test(edx, Immediate(kSmiTagMask)); | 740 __ JumpIfSmi(edx, &slow); |
| 717 __ j(zero, &slow); | |
| 718 // Get the map from the receiver. | 741 // Get the map from the receiver. |
| 719 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); | 742 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
| 720 // Check that the receiver does not require access checks. We need | 743 // Check that the receiver does not require access checks. We need |
| 721 // to do this because this generic stub does not perform map checks. | 744 // to do this because this generic stub does not perform map checks. |
| 722 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), | 745 __ test_b(FieldOperand(edi, Map::kBitFieldOffset), |
| 723 1 << Map::kIsAccessCheckNeeded); | 746 1 << Map::kIsAccessCheckNeeded); |
| 724 __ j(not_zero, &slow); | 747 __ j(not_zero, &slow); |
| 725 // Check that the key is a smi. | 748 // Check that the key is a smi. |
| 726 __ test(ecx, Immediate(kSmiTagMask)); | 749 __ JumpIfNotSmi(ecx, &slow); |
| 727 __ j(not_zero, &slow); | |
| 728 __ CmpInstanceType(edi, JS_ARRAY_TYPE); | 750 __ CmpInstanceType(edi, JS_ARRAY_TYPE); |
| 729 __ j(equal, &array); | 751 __ j(equal, &array); |
| 730 // Check that the object is some kind of JS object. | 752 // Check that the object is some kind of JSObject. |
| 731 __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); | 753 __ CmpInstanceType(edi, FIRST_JS_RECEIVER_TYPE); |
| 732 __ j(below, &slow); | 754 __ j(below, &slow); |
| 755 __ CmpInstanceType(edi, JS_PROXY_TYPE); |
| 756 __ j(equal, &slow); |
| 757 __ CmpInstanceType(edi, JS_FUNCTION_PROXY_TYPE); |
| 758 __ j(equal, &slow); |
| 733 | 759 |
| 734 // Object case: Check key against length in the elements array. | 760 // Object case: Check key against length in the elements array. |
| 735 // eax: value | 761 // eax: value |
| 736 // edx: JSObject | 762 // edx: JSObject |
| 737 // ecx: key (a smi) | 763 // ecx: key (a smi) |
| 738 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); | 764 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
| 739 // Check that the object is in fast mode and writable. | 765 // Check that the object is in fast mode and writable. |
| 740 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); | 766 __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); |
| 741 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); | 767 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
| 742 __ j(below, &fast); | 768 __ j(below, &fast); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 814 argc); | 840 argc); |
| 815 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, | 841 Isolate::Current()->stub_cache()->GenerateProbe(masm, flags, edx, ecx, ebx, |
| 816 eax); | 842 eax); |
| 817 | 843 |
| 818 // If the stub cache probing failed, the receiver might be a value. | 844 // If the stub cache probing failed, the receiver might be a value. |
| 819 // For value objects, we use the map of the prototype objects for | 845 // For value objects, we use the map of the prototype objects for |
| 820 // the corresponding JSValue for the cache and that is what we need | 846 // the corresponding JSValue for the cache and that is what we need |
| 821 // to probe. | 847 // to probe. |
| 822 // | 848 // |
| 823 // Check for number. | 849 // Check for number. |
| 824 __ test(edx, Immediate(kSmiTagMask)); | 850 __ JumpIfSmi(edx, &number); |
| 825 __ j(zero, &number); | |
| 826 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); | 851 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, ebx); |
| 827 __ j(not_equal, &non_number); | 852 __ j(not_equal, &non_number); |
| 828 __ bind(&number); | 853 __ bind(&number); |
| 829 StubCompiler::GenerateLoadGlobalFunctionPrototype( | 854 StubCompiler::GenerateLoadGlobalFunctionPrototype( |
| 830 masm, Context::NUMBER_FUNCTION_INDEX, edx); | 855 masm, Context::NUMBER_FUNCTION_INDEX, edx); |
| 831 __ jmp(&probe); | 856 __ jmp(&probe); |
| 832 | 857 |
| 833 // Check for string. | 858 // Check for string. |
| 834 __ bind(&non_number); | 859 __ bind(&non_number); |
| 835 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); | 860 __ CmpInstanceType(ebx, FIRST_NONSTRING_TYPE); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 862 // ----------- S t a t e ------------- | 887 // ----------- S t a t e ------------- |
| 863 // -- ecx : name | 888 // -- ecx : name |
| 864 // -- edi : function | 889 // -- edi : function |
| 865 // -- esp[0] : return address | 890 // -- esp[0] : return address |
| 866 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 891 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 867 // -- ... | 892 // -- ... |
| 868 // -- esp[(argc + 1) * 4] : receiver | 893 // -- esp[(argc + 1) * 4] : receiver |
| 869 // ----------------------------------- | 894 // ----------------------------------- |
| 870 | 895 |
| 871 // Check that the result is not a smi. | 896 // Check that the result is not a smi. |
| 872 __ test(edi, Immediate(kSmiTagMask)); | 897 __ JumpIfSmi(edi, miss); |
| 873 __ j(zero, miss); | |
| 874 | 898 |
| 875 // Check that the value is a JavaScript function, fetching its map into eax. | 899 // Check that the value is a JavaScript function, fetching its map into eax. |
| 876 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); | 900 __ CmpObjectType(edi, JS_FUNCTION_TYPE, eax); |
| 877 __ j(not_equal, miss); | 901 __ j(not_equal, miss); |
| 878 | 902 |
| 879 // Invoke the function. | 903 // Invoke the function. |
| 880 ParameterCount actual(argc); | 904 ParameterCount actual(argc); |
| 881 __ InvokeFunction(edi, actual, JUMP_FUNCTION); | 905 __ InvokeFunction(edi, actual, JUMP_FUNCTION, |
| 906 NullCallWrapper(), CALL_AS_METHOD); |
| 882 } | 907 } |
| 883 | 908 |
| 884 // The generated code falls through if the call should be handled by runtime. | 909 // The generated code falls through if the call should be handled by runtime. |
| 885 static void GenerateCallNormal(MacroAssembler* masm, int argc) { | 910 static void GenerateCallNormal(MacroAssembler* masm, int argc) { |
| 886 // ----------- S t a t e ------------- | 911 // ----------- S t a t e ------------- |
| 887 // -- ecx : name | 912 // -- ecx : name |
| 888 // -- esp[0] : return address | 913 // -- esp[0] : return address |
| 889 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 914 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 890 // -- ... | 915 // -- ... |
| 891 // -- esp[(argc + 1) * 4] : receiver | 916 // -- esp[(argc + 1) * 4] : receiver |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 | 968 |
| 944 // Move result to edi and exit the internal frame. | 969 // Move result to edi and exit the internal frame. |
| 945 __ mov(edi, eax); | 970 __ mov(edi, eax); |
| 946 __ LeaveInternalFrame(); | 971 __ LeaveInternalFrame(); |
| 947 | 972 |
| 948 // Check if the receiver is a global object of some sort. | 973 // Check if the receiver is a global object of some sort. |
| 949 // This can happen only for regular CallIC but not KeyedCallIC. | 974 // This can happen only for regular CallIC but not KeyedCallIC. |
| 950 if (id == IC::kCallIC_Miss) { | 975 if (id == IC::kCallIC_Miss) { |
| 951 Label invoke, global; | 976 Label invoke, global; |
| 952 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver | 977 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); // receiver |
| 953 __ test(edx, Immediate(kSmiTagMask)); | 978 __ JumpIfSmi(edx, &invoke, Label::kNear); |
| 954 __ j(zero, &invoke, Label::kNear); | |
| 955 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); | 979 __ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
| 956 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); | 980 __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); |
| 957 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); | 981 __ cmp(ebx, JS_GLOBAL_OBJECT_TYPE); |
| 958 __ j(equal, &global, Label::kNear); | 982 __ j(equal, &global, Label::kNear); |
| 959 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); | 983 __ cmp(ebx, JS_BUILTINS_OBJECT_TYPE); |
| 960 __ j(not_equal, &invoke, Label::kNear); | 984 __ j(not_equal, &invoke, Label::kNear); |
| 961 | 985 |
| 962 // Patch the receiver on the stack. | 986 // Patch the receiver on the stack. |
| 963 __ bind(&global); | 987 __ bind(&global); |
| 964 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); | 988 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1037 // ----------------------------------- | 1061 // ----------------------------------- |
| 1038 | 1062 |
| 1039 // Get the receiver of the function from the stack; 1 ~ return address. | 1063 // Get the receiver of the function from the stack; 1 ~ return address. |
| 1040 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1064 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1041 | 1065 |
| 1042 Label do_call, slow_call, slow_load, slow_reload_receiver; | 1066 Label do_call, slow_call, slow_load, slow_reload_receiver; |
| 1043 Label check_number_dictionary, check_string, lookup_monomorphic_cache; | 1067 Label check_number_dictionary, check_string, lookup_monomorphic_cache; |
| 1044 Label index_smi, index_string; | 1068 Label index_smi, index_string; |
| 1045 | 1069 |
| 1046 // Check that the key is a smi. | 1070 // Check that the key is a smi. |
| 1047 __ test(ecx, Immediate(kSmiTagMask)); | 1071 __ JumpIfNotSmi(ecx, &check_string); |
| 1048 __ j(not_zero, &check_string); | |
| 1049 | 1072 |
| 1050 __ bind(&index_smi); | 1073 __ bind(&index_smi); |
| 1051 // Now the key is known to be a smi. This place is also jumped to from | 1074 // Now the key is known to be a smi. This place is also jumped to from |
| 1052 // where a numeric string is converted to a smi. | 1075 // where a numeric string is converted to a smi. |
| 1053 | 1076 |
| 1054 GenerateKeyedLoadReceiverCheck( | 1077 GenerateKeyedLoadReceiverCheck( |
| 1055 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); | 1078 masm, edx, eax, Map::kHasIndexedInterceptor, &slow_call); |
| 1056 | 1079 |
| 1057 GenerateFastArrayLoad( | 1080 GenerateFastArrayLoad( |
| 1058 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); | 1081 masm, edx, ecx, eax, edi, &check_number_dictionary, &slow_load); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1071 // ecx: smi key | 1094 // ecx: smi key |
| 1072 // Check whether the elements is a number dictionary. | 1095 // Check whether the elements is a number dictionary. |
| 1073 __ CheckMap(eax, | 1096 __ CheckMap(eax, |
| 1074 isolate->factory()->hash_table_map(), | 1097 isolate->factory()->hash_table_map(), |
| 1075 &slow_load, | 1098 &slow_load, |
| 1076 DONT_DO_SMI_CHECK); | 1099 DONT_DO_SMI_CHECK); |
| 1077 __ mov(ebx, ecx); | 1100 __ mov(ebx, ecx); |
| 1078 __ SmiUntag(ebx); | 1101 __ SmiUntag(ebx); |
| 1079 // ebx: untagged index | 1102 // ebx: untagged index |
| 1080 // Receiver in edx will be clobbered, need to reload it on miss. | 1103 // Receiver in edx will be clobbered, need to reload it on miss. |
| 1081 GenerateNumberDictionaryLoad( | 1104 __ LoadFromNumberDictionary( |
| 1082 masm, &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); | 1105 &slow_reload_receiver, eax, ecx, ebx, edx, edi, edi); |
| 1083 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); | 1106 __ IncrementCounter(counters->keyed_call_generic_smi_dict(), 1); |
| 1084 __ jmp(&do_call); | 1107 __ jmp(&do_call); |
| 1085 | 1108 |
| 1086 __ bind(&slow_reload_receiver); | 1109 __ bind(&slow_reload_receiver); |
| 1087 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); | 1110 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1088 | 1111 |
| 1089 __ bind(&slow_load); | 1112 __ bind(&slow_load); |
| 1090 // This branch is taken when calling KeyedCallIC_Miss is neither required | 1113 // This branch is taken when calling KeyedCallIC_Miss is neither required |
| 1091 // nor beneficial. | 1114 // nor beneficial. |
| 1092 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); | 1115 __ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1138 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); | 1161 __ IncrementCounter(counters->keyed_call_generic_slow(), 1); |
| 1139 GenerateMiss(masm, argc); | 1162 GenerateMiss(masm, argc); |
| 1140 | 1163 |
| 1141 __ bind(&index_string); | 1164 __ bind(&index_string); |
| 1142 __ IndexFromHash(ebx, ecx); | 1165 __ IndexFromHash(ebx, ecx); |
| 1143 // Now jump to the place where smi keys are handled. | 1166 // Now jump to the place where smi keys are handled. |
| 1144 __ jmp(&index_smi); | 1167 __ jmp(&index_smi); |
| 1145 } | 1168 } |
| 1146 | 1169 |
| 1147 | 1170 |
| 1171 void KeyedCallIC::GenerateNonStrictArguments(MacroAssembler* masm, |
| 1172 int argc) { |
| 1173 // ----------- S t a t e ------------- |
| 1174 // -- ecx : name |
| 1175 // -- esp[0] : return address |
| 1176 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1177 // -- ... |
| 1178 // -- esp[(argc + 1) * 4] : receiver |
| 1179 // ----------------------------------- |
| 1180 Label slow, notin; |
| 1181 Factory* factory = masm->isolate()->factory(); |
| 1182 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
| 1183 Operand mapped_location = |
| 1184 GenerateMappedArgumentsLookup(masm, edx, ecx, ebx, eax, ¬in, &slow); |
| 1185 __ mov(edi, mapped_location); |
| 1186 GenerateFunctionTailCall(masm, argc, &slow); |
| 1187 __ bind(¬in); |
| 1188 // The unmapped lookup expects that the parameter map is in ebx. |
| 1189 Operand unmapped_location = |
| 1190 GenerateUnmappedArgumentsLookup(masm, ecx, ebx, eax, &slow); |
| 1191 __ cmp(unmapped_location, factory->the_hole_value()); |
| 1192 __ j(equal, &slow); |
| 1193 __ mov(edi, unmapped_location); |
| 1194 GenerateFunctionTailCall(masm, argc, &slow); |
| 1195 __ bind(&slow); |
| 1196 GenerateMiss(masm, argc); |
| 1197 } |
| 1198 |
| 1199 |
| 1148 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { | 1200 void KeyedCallIC::GenerateNormal(MacroAssembler* masm, int argc) { |
| 1149 // ----------- S t a t e ------------- | 1201 // ----------- S t a t e ------------- |
| 1150 // -- ecx : name | 1202 // -- ecx : name |
| 1151 // -- esp[0] : return address | 1203 // -- esp[0] : return address |
| 1152 // -- esp[(argc - n) * 4] : arg[n] (zero-based) | 1204 // -- esp[(argc - n) * 4] : arg[n] (zero-based) |
| 1153 // -- ... | 1205 // -- ... |
| 1154 // -- esp[(argc + 1) * 4] : receiver | 1206 // -- esp[(argc + 1) * 4] : receiver |
| 1155 // ----------------------------------- | 1207 // ----------------------------------- |
| 1156 | 1208 |
| 1157 // Check if the name is a string. | 1209 // Check if the name is a string. |
| 1158 Label miss; | 1210 Label miss; |
| 1159 __ test(ecx, Immediate(kSmiTagMask)); | 1211 __ JumpIfSmi(ecx, &miss); |
| 1160 __ j(zero, &miss); | |
| 1161 Condition cond = masm->IsObjectStringType(ecx, eax, eax); | 1212 Condition cond = masm->IsObjectStringType(ecx, eax, eax); |
| 1162 __ j(NegateCondition(cond), &miss); | 1213 __ j(NegateCondition(cond), &miss); |
| 1163 GenerateCallNormal(masm, argc); | 1214 GenerateCallNormal(masm, argc); |
| 1164 __ bind(&miss); | 1215 __ bind(&miss); |
| 1165 GenerateMiss(masm, argc); | 1216 GenerateMiss(masm, argc); |
| 1166 } | 1217 } |
| 1167 | 1218 |
| 1168 | 1219 |
| 1169 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { | 1220 void KeyedCallIC::GenerateMiss(MacroAssembler* masm, int argc) { |
| 1170 // ----------- S t a t e ------------- | 1221 // ----------- S t a t e ------------- |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1335 // elements of FixedArray type.), but currently is restricted to JSArray. | 1386 // elements of FixedArray type.), but currently is restricted to JSArray. |
| 1336 // Value must be a number, but only smis are accepted as the most common case. | 1387 // Value must be a number, but only smis are accepted as the most common case. |
| 1337 | 1388 |
| 1338 Label miss; | 1389 Label miss; |
| 1339 | 1390 |
| 1340 Register receiver = edx; | 1391 Register receiver = edx; |
| 1341 Register value = eax; | 1392 Register value = eax; |
| 1342 Register scratch = ebx; | 1393 Register scratch = ebx; |
| 1343 | 1394 |
| 1344 // Check that the receiver isn't a smi. | 1395 // Check that the receiver isn't a smi. |
| 1345 __ test(receiver, Immediate(kSmiTagMask)); | 1396 __ JumpIfSmi(receiver, &miss); |
| 1346 __ j(zero, &miss); | |
| 1347 | 1397 |
| 1348 // Check that the object is a JS array. | 1398 // Check that the object is a JS array. |
| 1349 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | 1399 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); |
| 1350 __ j(not_equal, &miss); | 1400 __ j(not_equal, &miss); |
| 1351 | 1401 |
| 1352 // Check that elements are FixedArray. | 1402 // Check that elements are FixedArray. |
| 1353 // We rely on StoreIC_ArrayLength below to deal with all types of | 1403 // We rely on StoreIC_ArrayLength below to deal with all types of |
| 1354 // fast elements (including COW). | 1404 // fast elements (including COW). |
| 1355 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); | 1405 __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset)); |
| 1356 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); | 1406 __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch); |
| 1357 __ j(not_equal, &miss); | 1407 __ j(not_equal, &miss); |
| 1358 | 1408 |
| 1359 // Check that value is a smi. | 1409 // Check that value is a smi. |
| 1360 __ test(value, Immediate(kSmiTagMask)); | 1410 __ JumpIfNotSmi(value, &miss); |
| 1361 __ j(not_zero, &miss); | |
| 1362 | 1411 |
| 1363 // Prepare tail call to StoreIC_ArrayLength. | 1412 // Prepare tail call to StoreIC_ArrayLength. |
| 1364 __ pop(scratch); | 1413 __ pop(scratch); |
| 1365 __ push(receiver); | 1414 __ push(receiver); |
| 1366 __ push(value); | 1415 __ push(value); |
| 1367 __ push(scratch); // return address | 1416 __ push(scratch); // return address |
| 1368 | 1417 |
| 1369 ExternalReference ref = | 1418 ExternalReference ref = |
| 1370 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); | 1419 ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate()); |
| 1371 __ TailCallExternalReference(ref, 2, 1); | 1420 __ TailCallExternalReference(ref, 2, 1); |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1589 Condition cc = *jmp_address == Assembler::kJncShortOpcode | 1638 Condition cc = *jmp_address == Assembler::kJncShortOpcode |
| 1590 ? not_zero | 1639 ? not_zero |
| 1591 : zero; | 1640 : zero; |
| 1592 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 1641 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
| 1593 } | 1642 } |
| 1594 | 1643 |
| 1595 | 1644 |
| 1596 } } // namespace v8::internal | 1645 } } // namespace v8::internal |
| 1597 | 1646 |
| 1598 #endif // V8_TARGET_ARCH_IA32 | 1647 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |