| Index: src/arm/macro-assembler-arm.cc
|
| ===================================================================
|
| --- src/arm/macro-assembler-arm.cc (revision 10578)
|
| +++ src/arm/macro-assembler-arm.cc (working copy)
|
| @@ -1882,6 +1882,77 @@
|
| }
|
|
|
|
|
| +void MacroAssembler::CompareMapRoot(Register obj,
|
| + Register scratch,
|
| + Heap::RootListIndex index) {
|
| + Heap* heap = isolate()->heap();
|
| + Object* root = heap->roots_array_start()[index];
|
| + ASSERT(root->IsMap());
|
| + if (!scratch.is(no_reg) && CanDoEfficientMapComparison(Map::cast(root))) {
|
| + EfficientMapComparisonPrepare(obj, scratch);
|
| + EfficientMapComparison(scratch, Map::cast(root));
|
| + } else {
|
| + CompareRoot(obj, index);
|
| + }
|
| +}
|
| +
|
| +
|
| +bool MacroAssembler::CanDoEfficientMapComparison(Map* map) {
|
| + // The serializer does not know how to fix these instructions to reflect the
|
| + // new position of the maps when deserializing.
|
| + if (Serializer::enabled()) return false;
|
| + // We need either movw or ubfx to make this work.
|
| + if (!CpuFeatures::IsSupported(ARMv7)) return false;
|
| + uint32_t map_addr = reinterpret_cast<uintptr_t>(map);
|
| + uintptr_t page_number = map_addr >> kPageSizeBits;
|
| + // Only even map pages are guaranteed to be alias-free with the other map
|
| + // pages in the first 21 bits.
|
| + if ((page_number & 1) != 0) return false;
|
| + return true;
|
| +}
|
| +
|
| +
|
| +void MacroAssembler::EfficientMapComparisonPrepare(
|
| + Register obj, Register scratch) {
|
| + // It's OK for obj and scratch to be the same register.
|
| + ASSERT(!obj.is(ip));
|
| + ASSERT(!scratch.is(ip));
|
| + // Add 1 in order to get the last bit of the map page number.
|
| + if (emit_debug_code()) {
|
| + ldr(ip, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| + ldrb(ip, FieldMemOperand(ip, Map::kInstanceTypeOffset));
|
| + cmp(ip, Operand(MAP_TYPE));
|
| + Label ok;
|
| + b(eq, &ok);
|
| + stop("oops");
|
| + bind(&ok);
|
| + }
|
| + Ubfx(scratch,
|
| + obj,
|
| + Map::kMapSizeBits, // LSB.
|
| + 1 + kPageSizeBits - Map::kMapSizeBits);
|
| +}
|
| +
|
| +
|
| +// Makes use of the fact that maps do not move.
|
| +void MacroAssembler::EfficientMapComparison(Register significant_map_bits,
|
| + Map* map) {
|
| + ASSERT(CanDoEfficientMapComparison(map));
|
| + ASSERT(Map::kSize >= 1 << Map::kMapSizeBits);
|
| +
|
| + uint32_t map_addr = reinterpret_cast<uintptr_t>(map);
|
| + uintptr_t intra_page_address_and_last_bit_of_page_number =
|
| + map_addr & ((1 << (kPageSizeBits + 1)) - 1);
|
| + // This will be a movw unless the pages are very large. This is where we
|
| + // make use of maps not moving. If they start moving we have to emit reloc
|
| + // info here for this instruction.
|
| + uint16_t map_index =
|
| + intra_page_address_and_last_bit_of_page_number >> Map::kMapSizeBits;
|
| + mov(ip, Operand(map_index, RelocInfo::MAP_SIGNATURE));
|
| + cmp(significant_map_bits, Operand(ip));
|
| +}
|
| +
|
| +
|
| void MacroAssembler::CompareRoot(Register obj,
|
| Heap::RootListIndex index) {
|
| ASSERT(!obj.is(ip));
|
| @@ -1943,7 +2014,7 @@
|
| // Ensure that the object is a heap number
|
| CheckMap(value_reg,
|
| scratch1,
|
| - isolate()->factory()->heap_number_map(),
|
| + Heap::kHeapNumberMapRootIndex,
|
| fail,
|
| DONT_DO_SMI_CHECK);
|
|
|
| @@ -2014,21 +2085,57 @@
|
| }
|
|
|
|
|
| +void MacroAssembler::CompareMaps(Register possible_map,
|
| + Register scratch,
|
| + Map* map1,
|
| + Map* map2,
|
| + Map* map3,
|
| + Label* early_success) {
|
| + if (!scratch.is(no_reg) &&
|
| + CanDoEfficientMapComparison(map1) &&
|
| + (map2 == NULL || CanDoEfficientMapComparison(map2)) &&
|
| + (map3 == NULL || CanDoEfficientMapComparison(map3))) {
|
| + EfficientMapComparisonPrepare(possible_map, scratch);
|
| + EfficientMapComparison(scratch, map1);
|
| + if (map2 != NULL) {
|
| + b(eq, early_success);
|
| + EfficientMapComparison(scratch, map2);
|
| + }
|
| + if (map3 != NULL) {
|
| + b(eq, early_success);
|
| + EfficientMapComparison(scratch, map3);
|
| + }
|
| + } else {
|
| + cmp(possible_map, Operand(Handle<Map>(map1)));
|
| + if (map2 != NULL) {
|
| + b(eq, early_success);
|
| + cmp(possible_map, Operand(Handle<Map>(map2)));
|
| + }
|
| + if (map3 != NULL) {
|
| + b(eq, early_success);
|
| + cmp(possible_map, Operand(Handle<Map>(map3)));
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| void MacroAssembler::CompareMap(Register obj,
|
| + Register map_register,
|
| Register scratch,
|
| Handle<Map> map,
|
| Label* early_success,
|
| CompareMapMode mode) {
|
| - ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| - cmp(scratch, Operand(map));
|
| + ldr(map_register, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| + Map* map1 = *map;
|
| + Map* map2 = NULL;
|
| + Map* map3 = NULL;
|
| if (mode == ALLOW_ELEMENT_TRANSITION_MAPS) {
|
| Map* transitioned_fast_element_map(
|
| map->LookupElementsTransitionMap(FAST_ELEMENTS, NULL));
|
| ASSERT(transitioned_fast_element_map == NULL ||
|
| map->elements_kind() != FAST_ELEMENTS);
|
| if (transitioned_fast_element_map != NULL) {
|
| - b(eq, early_success);
|
| - cmp(scratch, Operand(Handle<Map>(transitioned_fast_element_map)));
|
| + map2 = transitioned_fast_element_map;
|
| }
|
|
|
| Map* transitioned_double_map(
|
| @@ -2036,14 +2143,15 @@
|
| ASSERT(transitioned_double_map == NULL ||
|
| map->elements_kind() == FAST_SMI_ONLY_ELEMENTS);
|
| if (transitioned_double_map != NULL) {
|
| - b(eq, early_success);
|
| - cmp(scratch, Operand(Handle<Map>(transitioned_double_map)));
|
| + map3 = transitioned_double_map;
|
| }
|
| }
|
| + CompareMaps(map_register, scratch, map1, map2, map3, early_success);
|
| }
|
|
|
|
|
| void MacroAssembler::CheckMap(Register obj,
|
| + Register map_register,
|
| Register scratch,
|
| Handle<Map> map,
|
| Label* fail,
|
| @@ -2054,7 +2162,7 @@
|
| }
|
|
|
| Label success;
|
| - CompareMap(obj, scratch, map, &success, mode);
|
| + CompareMap(obj, map_register, scratch, map, &success, mode);
|
| b(ne, fail);
|
| bind(&success);
|
| }
|
| @@ -2069,8 +2177,7 @@
|
| JumpIfSmi(obj, fail);
|
| }
|
| ldr(scratch, FieldMemOperand(obj, HeapObject::kMapOffset));
|
| - LoadRoot(ip, index);
|
| - cmp(scratch, ip);
|
| + CompareMapRoot(scratch, scratch, index);
|
| b(ne, fail);
|
| }
|
|
|
|
|