From 770e6ee8b84e0e65420fb9ae07bb9a5e9851cbee Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Fri, 9 Aug 2013 13:43:46 +0000 Subject: [PATCH] Fix/unify root handling in code generation. R=danno@chromium.org Review URL: https://codereview.chromium.org/22670004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16132 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/macro-assembler-arm.cc | 15 +++---- src/heap.cc | 6 +++ src/heap.h | 2 + src/ia32/code-stubs-ia32.cc | 55 ++++++------------------- src/ia32/macro-assembler-ia32.cc | 69 +++++++++++++++++++++++++------- src/ia32/macro-assembler-ia32.h | 13 ++++-- 6 files changed, 89 insertions(+), 71 deletions(-) diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index b9728ed04f..a56744bf59 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -375,16 +375,13 @@ void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index, Condition cond) { if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && - !Heap::RootCanBeWrittenAfterInitialization(index) && + isolate()->heap()->RootCanBeTreatedAsConstant(index) && !predictable_code_size()) { - Handle root(isolate()->heap()->roots_array_start()[index], - isolate()); - if (!isolate()->heap()->InNewSpace(*root)) { - // The CPU supports fast immediate values, and this root will never - // change. We will load it as a relocatable immediate value. - mov(destination, Operand(root), LeaveCC, cond); - return; - } + // The CPU supports fast immediate values, and this root will never + // change. We will load it as a relocatable immediate value. + Handle root(&isolate()->heap()->roots_array_start()[index]); + mov(destination, Operand(root), LeaveCC, cond); + return; } ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); } diff --git a/src/heap.cc b/src/heap.cc index d61d0d7a22..9d8a6fad99 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -3263,6 +3263,12 @@ bool Heap::RootCanBeWrittenAfterInitialization(Heap::RootListIndex root_index) { } +bool Heap::RootCanBeTreatedAsConstant(RootListIndex root_index) { + return !RootCanBeWrittenAfterInitialization(root_index) && + !InNewSpace(roots_array_start()[root_index]); +} + + Object* RegExpResultsCache::Lookup(Heap* heap, String* key_string, Object* key_pattern, diff --git a/src/heap.h b/src/heap.h index a25f8a51c9..78c0e5b26b 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1615,6 +1615,8 @@ class Heap { // Generated code can embed direct references to non-writable roots if // they are in new space. static bool RootCanBeWrittenAfterInitialization(RootListIndex root_index); + // Generated code can treat direct references to this root as constant. + bool RootCanBeTreatedAsConstant(RootListIndex root_index); MUST_USE_RESULT MaybeObject* NumberToString( Object* number, bool check_number_string_cache = true, diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 8721656634..12cc499a77 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -3956,11 +3956,7 @@ void NumberToStringStub::GenerateLookupNumberStringCache(MacroAssembler* masm, Register scratch = scratch2; // Load the number string cache. - ExternalReference roots_array_start = - ExternalReference::roots_array_start(masm->isolate()); - __ mov(scratch, Immediate(Heap::kNumberStringCacheRootIndex)); - __ mov(number_string_cache, - Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); + __ LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex); // Make the hash mask from the length of the number string cache. It // contains two elements (number and string) for each cache entry. __ mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset)); @@ -5010,9 +5006,6 @@ void InstanceofStub::Generate(MacroAssembler* masm) { static const int8_t kCmpEdiOperandByte2 = BitCast(0x3d); static const int8_t kMovEaxImmediateByte = BitCast(0xb8); - ExternalReference roots_array_start = - ExternalReference::roots_array_start(masm->isolate()); - ASSERT_EQ(object.code(), InstanceofStub::left().code()); ASSERT_EQ(function.code(), InstanceofStub::right().code()); @@ -5032,18 +5025,11 @@ void InstanceofStub::Generate(MacroAssembler* masm) { if (!HasCallSiteInlineCheck()) { // Look up the function and the map in the instanceof cache. Label miss; - __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); - __ cmp(function, Operand::StaticArray(scratch, - times_pointer_size, - roots_array_start)); + __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); __ j(not_equal, &miss, Label::kNear); - __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); - __ cmp(map, Operand::StaticArray( - scratch, times_pointer_size, roots_array_start)); + __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); __ j(not_equal, &miss, Label::kNear); - __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); - __ mov(eax, Operand::StaticArray( - scratch, times_pointer_size, roots_array_start)); + __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); __ bind(&miss); } @@ -5058,12 +5044,8 @@ void InstanceofStub::Generate(MacroAssembler* masm) { // Update the global instanceof or call site inlined cache with the current // map and function. The cached answer will be set when it is known below. if (!HasCallSiteInlineCheck()) { - __ mov(scratch, Immediate(Heap::kInstanceofCacheMapRootIndex)); - __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), - map); - __ mov(scratch, Immediate(Heap::kInstanceofCacheFunctionRootIndex)); - __ mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), - function); + __ StoreRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); + __ StoreRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); } else { // The constants for the code patching are based on no push instructions // at the call site. @@ -5097,10 +5079,8 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ bind(&is_instance); if (!HasCallSiteInlineCheck()) { - __ Set(eax, Immediate(0)); - __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); - __ mov(Operand::StaticArray(scratch, - times_pointer_size, roots_array_start), eax); + __ mov(eax, Immediate(0)); + __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); } else { // Get return address and delta to inlined map check. __ mov(eax, factory->true_value()); @@ -5119,10 +5099,8 @@ void InstanceofStub::Generate(MacroAssembler* masm) { __ bind(&is_not_instance); if (!HasCallSiteInlineCheck()) { - __ Set(eax, Immediate(Smi::FromInt(1))); - __ mov(scratch, Immediate(Heap::kInstanceofCacheAnswerRootIndex)); - __ mov(Operand::StaticArray( - scratch, times_pointer_size, roots_array_start), eax); + __ mov(eax, Immediate(Smi::FromInt(1))); + __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); } else { // Get return address and delta to inlined map check. __ mov(eax, factory->false_value()); @@ -5875,11 +5853,7 @@ void StringHelper::GenerateTwoCharacterStringTableProbe(MacroAssembler* masm, // Load the string table. Register string_table = c2; - ExternalReference roots_array_start = - ExternalReference::roots_array_start(masm->isolate()); - __ mov(scratch, Immediate(Heap::kStringTableRootIndex)); - __ mov(string_table, - Operand::StaticArray(scratch, times_pointer_size, roots_array_start)); + __ LoadRoot(string_table, Heap::kStringTableRootIndex); // Calculate capacity mask from the string table capacity. Register mask = scratch2; @@ -5967,12 +5941,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm, Register scratch) { // hash = (seed + character) + ((seed + character) << 10); if (Serializer::enabled()) { - ExternalReference roots_array_start = - ExternalReference::roots_array_start(masm->isolate()); - __ mov(scratch, Immediate(Heap::kHashSeedRootIndex)); - __ mov(scratch, Operand::StaticArray(scratch, - times_pointer_size, - roots_array_start)); + __ LoadRoot(scratch, Heap::kHashSeedRootIndex); __ SmiUntag(scratch); __ add(scratch, character); __ mov(hash, scratch); diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 8b1be3cf17..67a7c0d2b4 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -54,6 +54,60 @@ MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) } +void MacroAssembler::LoadRoot(Register destination, Heap::RootListIndex index) { + if (isolate()->heap()->RootCanBeTreatedAsConstant(index)) { + Handle value(&isolate()->heap()->roots_array_start()[index]); + mov(destination, value); + return; + } + ExternalReference roots_array_start = + ExternalReference::roots_array_start(isolate()); + mov(destination, Immediate(index)); + mov(destination, Operand::StaticArray(destination, + times_pointer_size, + roots_array_start)); +} + + +void MacroAssembler::StoreRoot(Register source, + Register scratch, + Heap::RootListIndex index) { + ASSERT(Heap::RootCanBeWrittenAfterInitialization(index)); + ExternalReference roots_array_start = + ExternalReference::roots_array_start(isolate()); + mov(scratch, Immediate(index)); + mov(Operand::StaticArray(scratch, times_pointer_size, roots_array_start), + source); +} + + +void MacroAssembler::CompareRoot(Register with, + Register scratch, + Heap::RootListIndex index) { + ExternalReference roots_array_start = + ExternalReference::roots_array_start(isolate()); + mov(scratch, Immediate(index)); + cmp(with, Operand::StaticArray(scratch, + times_pointer_size, + roots_array_start)); +} + + +void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { + ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index)); + Handle value(&isolate()->heap()->roots_array_start()[index]); + cmp(with, value); +} + + +void MacroAssembler::CompareRoot(const Operand& with, + Heap::RootListIndex index) { + ASSERT(isolate()->heap()->RootCanBeTreatedAsConstant(index)); + Handle value(&isolate()->heap()->roots_array_start()[index]); + cmp(with, value); +} + + void MacroAssembler::InNewSpace( Register object, Register scratch, @@ -432,21 +486,6 @@ void MacroAssembler::SafePush(const Immediate& x) { } -void MacroAssembler::CompareRoot(Register with, Heap::RootListIndex index) { - // see ROOT_ACCESSOR macro in factory.h - Handle value(&isolate()->heap()->roots_array_start()[index]); - cmp(with, value); -} - - -void MacroAssembler::CompareRoot(const Operand& with, - Heap::RootListIndex index) { - // see ROOT_ACCESSOR macro in factory.h - Handle value(&isolate()->heap()->roots_array_start()[index]); - cmp(with, value); -} - - void MacroAssembler::CmpObjectType(Register heap_object, InstanceType type, Register map) { diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index 165c9ce6d2..d537b0b2cb 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -61,6 +61,15 @@ class MacroAssembler: public Assembler { // macro assembler. MacroAssembler(Isolate* isolate, void* buffer, int size); + // Operations on roots in the root-array. + void LoadRoot(Register destination, Heap::RootListIndex index); + void StoreRoot(Register source, Register scratch, Heap::RootListIndex index); + void CompareRoot(Register with, Register scratch, Heap::RootListIndex index); + // These methods can only be used with constant roots (i.e. non-writable + // and not in new space). + void CompareRoot(Register with, Heap::RootListIndex index); + void CompareRoot(const Operand& with, Heap::RootListIndex index); + // --------------------------------------------------------------------------- // GC Support enum RememberedSetFinalAction { @@ -362,10 +371,6 @@ class MacroAssembler: public Assembler { void SafeSet(Register dst, const Immediate& x); void SafePush(const Immediate& x); - // Compare against a known root, e.g. undefined, null, true, ... - void CompareRoot(Register with, Heap::RootListIndex index); - void CompareRoot(const Operand& with, Heap::RootListIndex index); - // Compare object type for heap object. // Incoming register is heap_object and outgoing register is map. void CmpObjectType(Register heap_object, InstanceType type, Register map);