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

Unified Diff: src/arm/macro-assembler-arm.cc

Issue 9315032: ARM: Use ubfx and movw instructions to avoid a PC-relative load on Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 8 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « src/arm/macro-assembler-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698