Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(280)

Side by Side Diff: src/ia32/code-stubs-ia32.cc

Issue 7356013: Implement Object.prototype.hasOwnProperty in generated code. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 5507 matching lines...) Expand 10 before | Expand all | Expand 10 after
5518 void StringHelper::GenerateHashInit(MacroAssembler* masm, 5518 void StringHelper::GenerateHashInit(MacroAssembler* masm,
5519 Register hash, 5519 Register hash,
5520 Register character, 5520 Register character,
5521 Register scratch) { 5521 Register scratch) {
5522 // hash = character + (character << 10); 5522 // hash = character + (character << 10);
5523 __ mov(hash, character); 5523 __ mov(hash, character);
5524 __ shl(hash, 10); 5524 __ shl(hash, 10);
5525 __ add(hash, Operand(character)); 5525 __ add(hash, Operand(character));
5526 // hash ^= hash >> 6; 5526 // hash ^= hash >> 6;
5527 __ mov(scratch, hash); 5527 __ mov(scratch, hash);
5528 __ sar(scratch, 6); 5528 __ shr(scratch, 6);
Mads Ager (chromium) 2011/07/15 09:04:45 This looks wrong? The >> operator in C++ is arithm
5529 __ xor_(hash, Operand(scratch)); 5529 __ xor_(hash, Operand(scratch));
5530 } 5530 }
5531 5531
5532 5532
5533 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm, 5533 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
5534 Register hash, 5534 Register hash,
5535 Register character, 5535 Register character,
5536 Register scratch) { 5536 Register scratch) {
5537 // hash += character; 5537 // hash += character;
5538 __ add(hash, Operand(character)); 5538 __ add(hash, Operand(character));
5539 // hash += hash << 10; 5539 // hash += hash << 10;
5540 __ mov(scratch, hash); 5540 __ mov(scratch, hash);
5541 __ shl(scratch, 10); 5541 __ shl(scratch, 10);
5542 __ add(hash, Operand(scratch)); 5542 __ add(hash, Operand(scratch));
5543 // hash ^= hash >> 6; 5543 // hash ^= hash >> 6;
5544 __ mov(scratch, hash); 5544 __ mov(scratch, hash);
5545 __ sar(scratch, 6); 5545 __ shr(scratch, 6);
5546 __ xor_(hash, Operand(scratch)); 5546 __ xor_(hash, Operand(scratch));
5547 } 5547 }
5548 5548
5549 5549
5550 void StringHelper::GenerateHashGetHash(MacroAssembler* masm, 5550 void StringHelper::GenerateHashGetHash(MacroAssembler* masm,
5551 Register hash, 5551 Register hash,
5552 Register scratch) { 5552 Register scratch) {
5553 // hash += hash << 3; 5553 // hash += hash << 3;
5554 __ mov(scratch, hash); 5554 __ mov(scratch, hash);
5555 __ shl(scratch, 3); 5555 __ shl(scratch, 3);
5556 __ add(hash, Operand(scratch)); 5556 __ add(hash, Operand(scratch));
5557 // hash ^= hash >> 11; 5557 // hash ^= hash >> 11;
5558 __ mov(scratch, hash); 5558 __ mov(scratch, hash);
5559 __ sar(scratch, 11); 5559 __ shr(scratch, 11);
5560 __ xor_(hash, Operand(scratch)); 5560 __ xor_(hash, Operand(scratch));
5561 // hash += hash << 15; 5561 // hash += hash << 15;
5562 __ mov(scratch, hash); 5562 __ mov(scratch, hash);
5563 __ shl(scratch, 15); 5563 __ shl(scratch, 15);
5564 __ add(hash, Operand(scratch)); 5564 __ add(hash, Operand(scratch));
5565 5565
5566 // if (hash == 0) hash = 27; 5566 // if (hash == 0) hash = 27;
5567 Label hash_not_zero; 5567 Label hash_not_zero;
5568 __ test(hash, Operand(hash)); 5568 __ test(hash, Operand(hash));
5569 __ j(not_zero, &hash_not_zero, Label::kNear); 5569 __ j(not_zero, &hash_not_zero, Label::kNear);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
5747 __ bind(&compare_chars); 5747 __ bind(&compare_chars);
5748 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2, 5748 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
5749 &strings_not_equal, Label::kNear); 5749 &strings_not_equal, Label::kNear);
5750 5750
5751 // Characters are equal. 5751 // Characters are equal.
5752 __ Set(eax, Immediate(Smi::FromInt(EQUAL))); 5752 __ Set(eax, Immediate(Smi::FromInt(EQUAL)));
5753 __ ret(0); 5753 __ ret(0);
5754 } 5754 }
5755 5755
5756 5756
5757 void StringCompareStub::GenerateFlatAsciiStringEquals(
5758 MacroAssembler* masm,
5759 Register left,
5760 Register right,
5761 Register scratch1,
5762 Register scratch2,
5763 Label* strings_not_equal) {
5764 Register length = scratch1;
5765
5766 // Compare lengths.
5767 __ mov(length, FieldOperand(left, String::kLengthOffset));
5768 __ cmp(length, FieldOperand(right, String::kLengthOffset));
5769 __ j(not_equal, strings_not_equal);
5770
5771 // Check if the length is zero.
5772 Label strings_equal;
5773 STATIC_ASSERT(kSmiTag == 0);
5774 __ test(length, Operand(length));
5775 __ j(zero, &strings_equal, Label::kNear);
5776
5777 // Compare characters.
5778 GenerateAsciiCharsCompareLoop(masm, left, right, length, scratch2,
5779 strings_not_equal, Label::kNear);
5780
5781 // Characters are equal.
5782 __ bind(&strings_equal);
5783 }
5784
5785
5757 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm, 5786 void StringCompareStub::GenerateCompareFlatAsciiStrings(MacroAssembler* masm,
5758 Register left, 5787 Register left,
5759 Register right, 5788 Register right,
5760 Register scratch1, 5789 Register scratch1,
5761 Register scratch2, 5790 Register scratch2,
5762 Register scratch3) { 5791 Register scratch3) {
5763 Counters* counters = masm->isolate()->counters(); 5792 Counters* counters = masm->isolate()->counters();
5764 __ IncrementCounter(counters->string_compare_native(), 1); 5793 __ IncrementCounter(counters->string_compare_native(), 1);
5765 5794
5766 // Find minimum length. 5795 // Find minimum length.
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after
6251 __ shr(r0, String::kHashShift); 6280 __ shr(r0, String::kHashShift);
6252 __ push(r0); 6281 __ push(r0);
6253 __ CallStub(&stub); 6282 __ CallStub(&stub);
6254 6283
6255 __ test(r1, Operand(r1)); 6284 __ test(r1, Operand(r1));
6256 __ j(zero, miss); 6285 __ j(zero, miss);
6257 __ jmp(done); 6286 __ jmp(done);
6258 } 6287 }
6259 6288
6260 6289
6290 void StringDictionaryLookupStub::GenerateLookupWithComparisons(
6291 MacroAssembler* masm,
6292 Register dictionary,
6293 Register name,
6294 Register scratch1,
6295 Register scratch2,
6296 Register scratch3,
6297 Label* found_in_dictionary,
6298 Label* not_found_in_dictionary,
6299 Label* call_runtime) {
6300 // Check whether the name is an ASCII symbol or an ASCII string.
6301 // Other types are not supported.
6302 Label name_is_symbol;
6303 __ mov(scratch1, FieldOperand(name, HeapObject::kMapOffset));
6304 __ cmp(scratch1, masm->isolate()->factory()->ascii_symbol_map());
6305 __ j(equal, &name_is_symbol);
6306 __ cmp(scratch1, masm->isolate()->factory()->ascii_string_map());
6307 __ j(not_equal, call_runtime);
6308
6309 // If the name is an ASCII string, it might not yet have its hash
6310 // code computed.
6311 Label name_has_hash_code;
6312 __ cmp(FieldOperand(name, String::kHashFieldOffset),
6313 Immediate(String::kEmptyHashField));
6314 __ j(not_equal, &name_has_hash_code);
6315
6316 // Load the string length and check it's not zero and not too big.
6317 __ mov(scratch1, FieldOperand(name, String::kLengthOffset));
6318 __ SmiUntag(scratch1);
6319 __ test(scratch1, Operand(scratch1));
6320 __ j(zero, call_runtime);
6321 __ cmp(scratch1, String::kMaxHashCalcLength);
6322 __ j(greater, call_runtime);
6323
6324 // Load the first char and check it's not numeric. Numeric strings
6325 // have a different hashing algorithm.
6326 Label not_an_array_index;
6327 Register character = scratch2;
6328 __ movzx_b(character, FieldOperand(name, SeqAsciiString::kHeaderSize));
6329 __ cmp(character, '9');
6330 __ j(greater, &not_an_array_index, Label::kNear);
6331 __ cmp(character, '0');
6332 __ j(greater_equal, call_runtime);
6333 __ bind(&not_an_array_index);
6334
6335 // Save the dictionary and the string length on the stack to free up
6336 // registers.
6337 __ push(dictionary);
6338 Operand length = Operand(esp, 0);
6339 __ push(scratch1);
6340
6341 // Hash the first (already loaded) char.
6342 Register index = scratch1;
6343 __ Set(index, Immediate(0));
6344 Register hash = dictionary;
6345 StringHelper::GenerateHashInit(masm, hash, character, scratch3);
6346
6347 // Hash the rest in a loop.
6348 Label hash_loop, hash_loop_done;
6349 __ bind(&hash_loop);
6350 __ add(Operand(index), Immediate(1));
6351 __ cmp(index, length);
6352 __ j(above_equal, &hash_loop_done, Label::kNear);
6353 __ movzx_b(character, FieldOperand(name,
6354 index, times_1,
6355 SeqAsciiString::kHeaderSize));
6356 StringHelper::GenerateHashAddCharacter(masm, hash, character, scratch3);
6357 __ jmp(&hash_loop, Label::kNear);
6358 __ bind(&hash_loop_done);
6359
6360 // Store the computed hash code in the name string.
6361 StringHelper::GenerateHashGetHash(masm, hash, scratch3);
6362 __ shl(hash, String::kHashShift);
6363 __ or_(hash, String::kIsNotArrayIndexMask);
6364 __ mov(FieldOperand(name, String::kHashFieldOffset), hash);
6365 // Restore the stack state.
6366 __ pop(dictionary); // Drop TOS.
6367 __ pop(dictionary);
6368
6369 __ bind(&name_has_hash_code);
6370 GenerateUnrolledComparisons(masm,
6371 NAME_IS_ASCII_STRING_WITH_HASH,
6372 dictionary,
6373 name,
6374 scratch1,
6375 scratch2,
6376 scratch3,
6377 found_in_dictionary,
6378 not_found_in_dictionary,
6379 call_runtime);
6380
6381 __ bind(&name_is_symbol);
6382 GenerateUnrolledComparisons(masm,
6383 NAME_IS_ASCII_SYMBOL,
6384 dictionary,
6385 name,
6386 scratch1,
6387 scratch2,
6388 scratch3,
6389 found_in_dictionary,
6390 not_found_in_dictionary,
6391 call_runtime);
6392 }
6393
6394
6395 void StringDictionaryLookupStub::GenerateUnrolledComparisons(
6396 MacroAssembler* masm,
6397 NameType name_type,
6398 Register dictionary,
6399 Register name,
6400 Register scratch1,
6401 Register scratch2,
6402 Register scratch3,
6403 Label* found_in_dictionary,
6404 Label* not_found_in_dictionary,
6405 Label* call_runtime) {
6406 // Compute the mask.
6407 Register mask = scratch1;
6408 __ mov(mask, FieldOperand(dictionary, kCapacityOffset));
6409 __ SmiUntag(mask);
6410 __ dec(mask);
6411
6412 // Generate an unrolled loop that performs a few probes before
6413 // giving up. Measurements done on Gmail indicate that 2 probes
6414 // cover ~93% of loads from dictionaries.
6415 for (int i = 0; i < kInlinedProbes; i++) {
6416 Register index = scratch2;
6417 Register candidate = scratch3;
6418
6419 Label next_probe;
6420 // Compute the masked index: (hash + i + i * i) & mask.
6421 __ mov(index, FieldOperand(name, String::kHashFieldOffset));
6422 __ shr(index, String::kHashShift);
6423 if (i > 0) {
6424 __ add(Operand(index), Immediate(StringDictionary::GetProbeOffset(i)));
6425 }
6426 __ and_(index, Operand(mask));
6427
6428 // Scale the index by multiplying by the entry size.
6429 ASSERT(StringDictionary::kEntrySize == 3);
6430 __ lea(index, Operand(index, index, times_2, 0)); // index *= 3
6431
6432 // Load the entry.
6433 __ mov(candidate, FieldOperand(dictionary,
6434 index,
6435 times_pointer_size,
6436 kElementsStartOffset));
6437
6438 // Fast identity check.
6439 __ cmp(name, Operand(candidate));
6440 __ j(equal, found_in_dictionary);
6441
6442 // Check for the end of the hash chain.
6443 __ cmp(candidate, masm->isolate()->factory()->undefined_value());
6444 __ j(equal, not_found_in_dictionary);
6445
6446 // Check for the deleted entry marker.
6447 __ cmp(candidate, masm->isolate()->factory()->null_value());
6448 __ j(equal, &next_probe);
6449
6450 // Load the instance type of the candidate.
6451 __ mov(scratch2, FieldOperand(candidate, HeapObject::kMapOffset));
6452 __ movzx_b(scratch2, FieldOperand(scratch2, Map::kInstanceTypeOffset));
6453 if (name_type == NAME_IS_ASCII_SYMBOL) {
6454 // If both name and candidate are symbols, we can go to the next
6455 // probe.
6456 __ test_b(Operand(scratch2), kIsSymbolMask);
6457 __ j(not_zero, &next_probe);
6458 // Check if the candidate is a sequential ASCII string.
6459 __ cmp(scratch2, static_cast<int32_t>(ASCII_STRING_TYPE));
6460 __ j(not_equal, call_runtime);
6461 } else {
6462 ASSERT(name_type == NAME_IS_ASCII_STRING_WITH_HASH);
6463 // Check if the candidate is a sequential ASCII string or symbol.
6464 uint32_t candidate_mask =
6465 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask;
6466 uint32_t expected =
6467 kStringTag | kAsciiStringTag | kSeqStringTag;
6468 __ and_(scratch2, static_cast<int32_t>(candidate_mask));
6469 __ cmp(scratch2, static_cast<int32_t>(expected));
6470 __ j(not_equal, call_runtime);
6471 }
6472
6473 // Compare sequential ASCII strings.
6474 Label strings_not_equal;
6475 __ push(dictionary);
6476 __ push(name);
6477 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
6478 name,
6479 candidate,
6480 scratch2,
6481 dictionary,
6482 &strings_not_equal);
6483 __ pop(name);
6484 __ pop(dictionary);
6485 __ jmp(found_in_dictionary);
6486 __ bind(&strings_not_equal);
6487 __ pop(name);
6488 __ pop(dictionary);
6489
6490 __ bind(&next_probe);
6491 }
6492 __ jmp(call_runtime);
6493 }
6494
6495
6261 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { 6496 void StringDictionaryLookupStub::Generate(MacroAssembler* masm) {
6262 // Stack frame on entry: 6497 // Stack frame on entry:
6263 // esp[0 * kPointerSize]: return address. 6498 // esp[0 * kPointerSize]: return address.
6264 // esp[1 * kPointerSize]: key's hash. 6499 // esp[1 * kPointerSize]: key's hash.
6265 // esp[2 * kPointerSize]: key. 6500 // esp[2 * kPointerSize]: key.
6266 // Registers: 6501 // Registers:
6267 // dictionary_: StringDictionary to probe. 6502 // dictionary_: StringDictionary to probe.
6268 // result_: used as scratch. 6503 // result_: used as scratch.
6269 // index_: will hold an index of entry if lookup is successful. 6504 // index_: will hold an index of entry if lookup is successful.
6270 // might alias with result_. 6505 // might alias with result_.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
6339 __ Drop(1); 6574 __ Drop(1);
6340 __ ret(2 * kPointerSize); 6575 __ ret(2 * kPointerSize);
6341 6576
6342 __ bind(&not_in_dictionary); 6577 __ bind(&not_in_dictionary);
6343 __ mov(result_, Immediate(0)); 6578 __ mov(result_, Immediate(0));
6344 __ Drop(1); 6579 __ Drop(1);
6345 __ ret(2 * kPointerSize); 6580 __ ret(2 * kPointerSize);
6346 } 6581 }
6347 6582
6348 6583
6584 void HasOwnPropertyStub::Generate(MacroAssembler* masm) {
6585 Register object = eax;
6586 Register map = ebx;
6587 Register name = ecx;
6588 Register scratch1 = edx;
6589 Register scratch2 = edi;
6590 Label call_runtime;
6591
6592 // Load the arguments.
6593 __ mov(object, Operand(esp, 2 * kPointerSize));
6594 __ mov(name, Operand(esp, 1 * kPointerSize));
6595
6596 if (FLAG_debug_code) {
6597 Label not_smi;
6598 __ JumpIfNotSmi(name, &not_smi, Label::kNear);
6599 __ Abort("HasOwnPropertyStub: name is a smi");
6600 __ bind(&not_smi);
6601 __ mov(scratch1, FieldOperand(name, HeapObject::kMapOffset));
6602 __ test_b(FieldOperand(scratch1, Map::kInstanceTypeOffset),
6603 kIsNotStringMask);
6604 __ Assert(not_zero, "HasOwnPropertyStub: name is not a string");
6605 }
6606
6607 // Make sure the object is a non-special JS object with no elements,
6608 // interceptors, or hidden prototypes.
6609 // TODO(vitalyr): access check?
Mads Ager (chromium) 2011/07/15 09:04:45 Yes, I'm pretty sure you need to exclude objects t
6610 __ JumpIfSmi(object, &call_runtime);
6611 __ mov(map, FieldOperand(object, HeapObject::kMapOffset));
6612 __ CmpInstanceType(map, JS_OBJECT_TYPE);
Mads Ager (chromium) 2011/07/15 09:04:45 Do you want to be that restrictive? You don't want
6613 __ j(not_equal, &call_runtime);
6614 __ cmp(FieldOperand(object, JSObject::kElementsOffset),
6615 masm->isolate()->factory()->empty_fixed_array());
6616 __ j(not_equal, &call_runtime);
6617 __ test_b(FieldOperand(map, Map::kBitFieldOffset),
6618 (1 << Map::kHasNamedInterceptor) |
6619 (1 << Map::kHasIndexedInterceptor));
6620 __ j(not_zero, &call_runtime);
6621 __ mov(scratch1, FieldOperand(map, Map::kPrototypeOffset));
6622 __ mov(scratch1, FieldOperand(scratch1, HeapObject::kMapOffset));
6623 __ test_b(FieldOperand(scratch1, Map::kBitFieldOffset),
Mads Ager (chromium) 2011/07/15 09:04:45 You are disregarding objects with hidden prototype
6624 (1 << Map::kIsHiddenPrototype));
6625 __ j(not_zero, &call_runtime);
6626
6627 // Does the object have fast properties?
6628 Label slow_properties;
6629 __ mov(scratch1, FieldOperand(object, JSObject::kPropertiesOffset));
6630 __ cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
6631 masm->isolate()->factory()->fixed_array_map());
6632 __ j(not_equal, &slow_properties);
6633
6634 // Handle fast properties.
6635 GenerateFastPropertiesCase(masm,
6636 map,
6637 name,
6638 object,
6639 scratch1,
6640 scratch2,
6641 &call_runtime);
6642
Mads Ager (chromium) 2011/07/15 09:04:45 Add an abort here so it is clear that there is no
6643 // Handle slow properties.
6644 __ bind(&slow_properties);
6645 GenerateSlowPropertiesCase(masm,
6646 object,
6647 name,
6648 map,
6649 scratch1,
6650 scratch2,
6651 &call_runtime);
6652
Mads Ager (chromium) 2011/07/15 09:04:45 Ditto, add an abort?
6653 __ bind(&call_runtime);
6654 __ TailCallRuntime(Runtime::kHasOwnProperty, 2, 1);
6655 }
6656
6657
6658 void HasOwnPropertyStub::GenerateFastPropertiesCase(MacroAssembler* masm,
6659 Register map,
6660 Register name,
6661 Register scratch1,
6662 Register scratch2,
6663 Register scratch3,
6664 Label* call_runtime) {
6665 // Load the descritor array from the map.
6666 Register descriptor_array = map;
6667 Label not_found_in_descriptors;
6668 __ mov(descriptor_array,
6669 FieldOperand(map, Map::kInstanceDescriptorsOrBitField3Offset));
6670 map = no_reg;
6671 __ JumpIfSmi(descriptor_array, &not_found_in_descriptors);
6672
6673 // Check the name is a symbol or a sequential ASCII string. We don't
6674 // support comparison of other string types here.
6675 Label name_is_not_symbol;
6676 __ mov(scratch1, FieldOperand(name, HeapObject::kMapOffset));
6677 __ movzx_b(scratch1, FieldOperand(scratch1, Map::kInstanceTypeOffset));
6678 __ test_b(Operand(scratch1), kIsSymbolMask);
6679 __ j(zero, &name_is_not_symbol);
6680 GenerateDescriptorArrayLookup(masm,
6681 NAME_IS_SYMBOL,
6682 descriptor_array,
6683 name,
6684 scratch1,
6685 scratch2,
6686 scratch3,
6687 &not_found_in_descriptors,
6688 call_runtime);
6689 __ bind(&name_is_not_symbol);
6690 uint32_t mask = kStringRepresentationMask | kStringEncodingMask;
6691 uint32_t expected = kSeqStringTag | kAsciiStringTag;
6692 __ and_(scratch1, static_cast<int32_t>(mask));
6693 __ cmp(scratch1, static_cast<int32_t>(expected));
6694 __ j(not_equal, call_runtime);
6695 GenerateDescriptorArrayLookup(masm,
6696 NAME_IS_SEQUENTIAL_ASCII,
6697 descriptor_array,
6698 name,
6699 scratch1,
6700 scratch2,
6701 scratch3,
6702 &not_found_in_descriptors,
6703 call_runtime);
6704
6705 // Did not find a descriptor corresponding to the given property
6706 // name.
6707 __ bind(&not_found_in_descriptors);
6708 __ mov(eax, masm->isolate()->factory()->false_value());
6709 __ ret(2);
6710 }
6711
6712
6713 void HasOwnPropertyStub::GenerateDescriptorArrayLookup(
6714 MacroAssembler* masm,
6715 NameType name_type,
6716 Register descriptor_array,
6717 Register name,
6718 Register scratch1,
6719 Register scratch2,
6720 Register scratch3,
6721 Label* not_found_in_descriptors,
6722 Label* call_runtime) {
6723 // Setup the lookup loop.
6724 Register index = scratch1;
6725 __ Set(index, Immediate(Smi::FromInt(DescriptorArray::kFirstIndex - 1)));
6726 Operand length = FieldOperand(descriptor_array, FixedArray::kLengthOffset);
6727
6728 // Loop over the descriptor array keys. Both index and length are
6729 // smi tagged.
6730 Register candidate = scratch2;
6731 Label loop, found_in_descriptors;
6732 __ bind(&loop);
6733 __ add(Operand(index), Immediate(Smi::FromInt(1)));
6734 __ cmp(index, length);
6735 __ j(greater_equal, not_found_in_descriptors);
6736 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
6737 Operand candidate_operand = FieldOperand(descriptor_array,
6738 index, times_half_pointer_size,
6739 FixedArray::kHeaderSize);
6740 if (name_type == NAME_IS_SYMBOL) {
6741 // If the property name is a symbol, we can do a fast identity
6742 // check only, because descriptor arrays always contain symbols.
6743 __ cmp(name, candidate_operand);
6744 __ j(not_equal, &loop, Label::kNear);
6745 } else {
6746 ASSERT(name_type == NAME_IS_SEQUENTIAL_ASCII);
6747 // If the property name is a sequential ASCII string, check that
6748 // the descriptor name is a sequential ASCII symbol.
6749 Label strings_not_equal;
6750 __ mov(candidate, candidate_operand);
6751 __ cmp(FieldOperand(candidate, HeapObject::kMapOffset),
6752 masm->isolate()->factory()->ascii_symbol_map());
6753 __ j(not_equal, call_runtime);
6754
6755 // Compare name and candidate strings. We have to temporarily save
6756 // registers on the stack.
6757 __ push(name);
6758 __ push(descriptor_array);
6759 StringCompareStub::GenerateFlatAsciiStringEquals(masm,
6760 name,
6761 candidate,
6762 scratch3,
6763 descriptor_array,
6764 &strings_not_equal);
6765 __ pop(descriptor_array);
6766 __ pop(name);
6767 __ jmp(&found_in_descriptors);
6768 __ bind(&strings_not_equal);
6769 __ pop(descriptor_array);
6770 __ pop(name);
6771 __ jmp(&loop);
6772 }
6773
6774 // Found a descriptor corresponding to the given property
6775 // name. Check the descriptor details to determine whether the
6776 // property exists or not.
6777 Register details = descriptor_array;
6778 Label do_return;
6779 __ bind(&found_in_descriptors);
6780 __ SmiUntag(index);
6781 __ sub(Operand(index), Immediate(DescriptorArray::kFirstIndex));
6782 __ mov(details, FieldOperand(descriptor_array,
6783 DescriptorArray::kContentArrayOffset));
6784 __ mov(details, FieldOperand(details,
6785 index, times_twice_pointer_size,
6786 FixedArray::kHeaderSize + kPointerSize));
6787 __ SmiUntag(details);
6788 __ and_(details, PropertyDetails::TypeField::mask());
6789 __ cmp(details,
6790 PropertyDetails::TypeField::encode(FIRST_PHANTOM_PROPERTY_TYPE));
6791 __ mov(eax, masm->isolate()->factory()->true_value());
6792 __ j(less, &do_return, Label::kNear);
6793 __ mov(eax, masm->isolate()->factory()->false_value());
6794 __ bind(&do_return);
6795 __ ret(2);
6796 }
6797
6798
6799 void HasOwnPropertyStub::GenerateSlowPropertiesCase(MacroAssembler* masm,
6800 Register object,
6801 Register name,
6802 Register scratch1,
6803 Register scratch2,
6804 Register scratch3,
6805 Label* call_runtime) {
6806 Label found_in_dictionary, not_found_in_dictionary;
6807 Register dictionary = object;
6808 __ mov(dictionary, FieldOperand(object, JSObject::kPropertiesOffset));
6809 StringDictionaryLookupStub::GenerateLookupWithComparisons(
6810 masm,
6811 dictionary,
6812 name,
6813 scratch1,
6814 scratch2,
6815 scratch3,
6816 &found_in_dictionary,
6817 &not_found_in_dictionary,
6818 call_runtime);
6819
6820 // Found a property with the given name in the property dictionary.
6821 __ bind(&found_in_dictionary);
6822 __ mov(eax, masm->isolate()->factory()->true_value());
6823 __ ret(2);
6824
6825 // Not found a property with the given name in the property dictionary.
6826 __ bind(&not_found_in_dictionary);
6827 __ mov(eax, masm->isolate()->factory()->false_value());
6828 __ ret(2);
6829 }
6830
6349 #undef __ 6831 #undef __
6350 6832
6351 } } // namespace v8::internal 6833 } } // namespace v8::internal
6352 6834
6353 #endif // V8_TARGET_ARCH_IA32 6835 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698