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
This commit is contained in:
parent
201c512dc7
commit
770e6ee8b8
@ -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<Object> 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<Object> root(&isolate()->heap()->roots_array_start()[index]);
|
||||
mov(destination, Operand(root), LeaveCC, cond);
|
||||
return;
|
||||
}
|
||||
ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond);
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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<int8_t, uint8_t>(0x3d);
|
||||
static const int8_t kMovEaxImmediateByte = BitCast<int8_t, uint8_t>(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);
|
||||
|
@ -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<Object> 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<Object> 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<Object> 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<Object> 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<Object> value(&isolate()->heap()->roots_array_start()[index]);
|
||||
cmp(with, value);
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CmpObjectType(Register heap_object,
|
||||
InstanceType type,
|
||||
Register map) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user