Commit a224db3a authored by lrn@chromium.org's avatar lrn@chromium.org

X64: Optimize access to external references.

Access to an ExternalReference in non-serializable code will try to use
an offset relative to the root-array register.
Since the root-array is in the Heap object, and the Heap object is in
the Isolate object, there's a good chance that any external data field
is within a 32-bit offset of the root array register.
It falls back on the original behavior if the serializer is enabled,
if the root register isn't initialized or if the offset is not representable
as a 32-bit value.

Review URL: http://codereview.chromium.org/6716018

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7315 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d5359e33
This diff is collapsed.
......@@ -760,7 +760,6 @@ void Deoptimizer::EntryGenerator::Generate() {
}
// Set up the roots register.
ExternalReference roots_address = ExternalReference::roots_address(isolate);
__ InitializeRootRegister();
__ InitializeSmiConstantRegister();
......
......@@ -633,7 +633,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
= ExternalReference::keyed_lookup_cache_keys(masm->isolate());
__ movq(rdi, rcx);
__ shl(rdi, Immediate(kPointerSizeLog2 + 1));
__ movq(kScratchRegister, cache_keys);
__ LoadAddress(kScratchRegister, cache_keys);
__ cmpq(rbx, Operand(kScratchRegister, rdi, times_1, 0));
__ j(not_equal, &slow);
__ cmpq(rax, Operand(kScratchRegister, rdi, times_1, kPointerSize));
......@@ -642,7 +642,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
// Get field offset, which is a 32-bit integer.
ExternalReference cache_field_offsets
= ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
__ movq(kScratchRegister, cache_field_offsets);
__ LoadAddress(kScratchRegister, cache_field_offsets);
__ movl(rdi, Operand(kScratchRegister, rcx, times_4, 0));
__ movzxbq(rcx, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
__ subq(rdi, rcx);
......@@ -1009,7 +1009,7 @@ static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
// Call the entry.
CEntryStub stub(1);
__ movq(rax, Immediate(2));
__ movq(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
__ LoadAddress(rbx, ExternalReference(IC_Utility(id), masm->isolate()));
__ CallStub(&stub);
// Move result to rdi and exit the internal frame.
......
......@@ -1911,7 +1911,8 @@ void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
Register map = ToRegister(instr->TempAt(0));
__ movq(map, FieldOperand(object, HeapObject::kMapOffset));
__ bind(deferred->map_check()); // Label for calculating code patching.
__ Move(kScratchRegister, factory()->the_hole_value());
__ movq(kScratchRegister, factory()->the_hole_value(),
RelocInfo::EMBEDDED_OBJECT);
__ cmpq(map, kScratchRegister); // Patched to cached map.
__ j(not_equal, &cache_miss);
// Patched to load either true or false.
......
This diff is collapsed.
......@@ -76,7 +76,49 @@ class MacroAssembler: public Assembler {
public:
MacroAssembler(void* buffer, int size);
// Prevent the use of the RootArray during the lifetime of this
// scope object.
class NoRootArrayScope BASE_EMBEDDED {
public:
explicit NoRootArrayScope(MacroAssembler* assembler)
: variable_(&assembler->root_array_available_),
old_value_(assembler->root_array_available_) {
assembler->root_array_available_ = false;
}
~NoRootArrayScope() {
*variable_ = old_value_;
}
private:
bool* variable_;
bool old_value_;
};
// Operand pointing to an external reference.
// May emit code to set up the scratch register. The operand is
// only guaranteed to be correct as long as the scratch register
// isn't changed.
// If the operand is used more than once, use a scratch register
// that is guaranteed not to be clobbered.
Operand ExternalOperand(ExternalReference reference,
Register scratch = kScratchRegister);
// Loads and stores the value of an external reference.
// Special case code for load and store to take advantage of
// load_rax/store_rax if possible/necessary.
// For other operations, just use:
// Operand operand = ExternalOperand(extref);
// operation(operand, ..);
void Load(Register destination, ExternalReference source);
void Store(ExternalReference destination, Register source);
// Loads the address of the external reference into the destination
// register.
void LoadAddress(Register destination, ExternalReference source);
// Returns the size of the code generated by LoadAddress.
// Used by CallSize(ExternalReference) to find the size of a call.
int LoadAddressSize(ExternalReference source);
// Operations on roots in the root-array.
void LoadRoot(Register destination, Heap::RootListIndex index);
void StoreRoot(Register source, Heap::RootListIndex index);
// Load a root value where the index (or part of it) is variable.
// The variable_offset register is added to the fixed_offset value
// to get the index into the root-array.
......@@ -86,7 +128,6 @@ class MacroAssembler: public Assembler {
void CompareRoot(Register with, Heap::RootListIndex index);
void CompareRoot(const Operand& with, Heap::RootListIndex index);
void PushRoot(Heap::RootListIndex index);
void StoreRoot(Register source, Heap::RootListIndex index);
// ---------------------------------------------------------------------------
// GC Support
......@@ -634,9 +675,7 @@ class MacroAssembler: public Assembler {
int CallSize(Address destination, RelocInfo::Mode rmode) {
return kCallInstructionLength;
}
int CallSize(ExternalReference ext) {
return kCallInstructionLength;
}
int CallSize(ExternalReference ext);
int CallSize(Handle<Code> code_object) {
// Code calls use 32-bit relative addressing.
return kShortCallInstructionLength;
......@@ -1024,6 +1063,7 @@ class MacroAssembler: public Assembler {
bool generating_stub_;
bool allow_stub_calls_;
bool root_array_available_;
// Returns a register holding the smi value. The register MUST NOT be
// modified. It may be the "smi 1 constant" register.
......
......@@ -63,6 +63,10 @@ namespace internal {
*
* The registers rax, rbx, r9 and r11 are free to use for computations.
* If changed to use r12+, they should be saved as callee-save registers.
* The macro assembler special registers r12 and r13 (kSmiConstantRegister,
* kRootRegister) aren't special during execution of RegExp code (they don't
* hold the values assumed when creating JS code), so no Smi or Root related
* macro operations can be used.
*
* Each call to a C++ method should retain these registers.
*
......@@ -111,6 +115,7 @@ RegExpMacroAssemblerX64::RegExpMacroAssemblerX64(
Mode mode,
int registers_to_save)
: masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
no_root_array_scope_(masm_),
code_relative_fixup_positions_(4),
mode_(mode),
num_registers_(registers_to_save),
......
......@@ -251,6 +251,7 @@ class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
inline void Drop();
MacroAssembler* masm_;
MacroAssembler::NoRootArrayScope no_root_array_scope_;
ZoneList<int> code_relative_fixup_positions_;
......
......@@ -52,7 +52,7 @@ static void ProbeTable(Isolate* isolate,
ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
Label miss;
__ movq(kScratchRegister, key_offset);
__ LoadAddress(kScratchRegister, key_offset);
// Check that the key in the entry matches the name.
// Multiply entry offset by 16 to get the entry address. Since the
// offset register already holds the entry offset times four, multiply
......@@ -398,7 +398,7 @@ static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly),
masm->isolate());
__ movq(rax, Immediate(5));
__ movq(rbx, ref);
__ LoadAddress(rbx, ref);
CEntryStub stub(1);
__ CallStub(&stub);
......@@ -1491,8 +1491,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
const int kAllocationDelta = 4;
// Load top.
__ movq(rcx, new_space_allocation_top);
__ movq(rcx, Operand(rcx, 0));
__ Load(rcx, new_space_allocation_top);
// Check if it's the end of elements.
__ lea(rdx, FieldOperand(rbx,
......@@ -1501,13 +1500,13 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ cmpq(rdx, rcx);
__ j(not_equal, &call_builtin);
__ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
__ movq(kScratchRegister, new_space_allocation_limit);
__ cmpq(rcx, Operand(kScratchRegister, 0));
Operand limit_operand =
masm()->ExternalOperand(new_space_allocation_limit);
__ cmpq(rcx, limit_operand);
__ j(above, &call_builtin);
// We fit and could grow elements.
__ movq(kScratchRegister, new_space_allocation_top);
__ movq(Operand(kScratchRegister, 0), rcx);
__ Store(new_space_allocation_top, rcx);
__ movq(rcx, Operand(rsp, argc * kPointerSize));
// Push the argument...
......
......@@ -96,6 +96,7 @@ static void EntryCode(MacroAssembler* masm) {
// Smi constant register is callee save.
__ push(v8::internal::kSmiConstantRegister);
__ InitializeSmiConstantRegister();
__ InitializeRootRegister();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment