d6ee366d5c
This is the initial round of optimizations for the LoadGlobalViaContextStub and StoreGlobalViaContextStub, basically turning them into platform code stubs to avoid the Crankshaft overhead in the fast case, and making the runtime interface cheaper. R=ishell@chromium.org BUG=chromium:510694 LOG=n Review URL: https://codereview.chromium.org/1238143002 Cr-Commit-Position: refs/heads/master@{#29834}
370 lines
11 KiB
C++
370 lines
11 KiB
C++
// Copyright 2012 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "src/v8.h"
|
|
|
|
#if V8_TARGET_ARCH_X64
|
|
|
|
#include "src/interface-descriptors.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
const Register CallInterfaceDescriptor::ContextRegister() { return rsi; }
|
|
|
|
|
|
const Register LoadDescriptor::ReceiverRegister() { return rdx; }
|
|
const Register LoadDescriptor::NameRegister() { return rcx; }
|
|
const Register LoadDescriptor::SlotRegister() { return rax; }
|
|
|
|
|
|
const Register LoadWithVectorDescriptor::VectorRegister() { return rbx; }
|
|
|
|
|
|
const Register StoreDescriptor::ReceiverRegister() { return rdx; }
|
|
const Register StoreDescriptor::NameRegister() { return rcx; }
|
|
const Register StoreDescriptor::ValueRegister() { return rax; }
|
|
|
|
|
|
const Register VectorStoreICTrampolineDescriptor::SlotRegister() { return rdi; }
|
|
|
|
|
|
const Register VectorStoreICDescriptor::VectorRegister() { return rbx; }
|
|
|
|
|
|
const Register StoreTransitionDescriptor::MapRegister() { return rbx; }
|
|
|
|
|
|
const Register LoadGlobalViaContextDescriptor::SlotRegister() { return rbx; }
|
|
const Register LoadGlobalViaContextDescriptor::NameRegister() { return rcx; }
|
|
|
|
|
|
const Register StoreGlobalViaContextDescriptor::SlotRegister() { return rbx; }
|
|
const Register StoreGlobalViaContextDescriptor::NameRegister() { return rcx; }
|
|
const Register StoreGlobalViaContextDescriptor::ValueRegister() { return rax; }
|
|
|
|
|
|
const Register InstanceofDescriptor::left() { return rax; }
|
|
const Register InstanceofDescriptor::right() { return rdx; }
|
|
|
|
|
|
const Register ArgumentsAccessReadDescriptor::index() { return rdx; }
|
|
const Register ArgumentsAccessReadDescriptor::parameter_count() { return rax; }
|
|
|
|
|
|
const Register ApiGetterDescriptor::function_address() { return r8; }
|
|
|
|
|
|
const Register MathPowTaggedDescriptor::exponent() { return rdx; }
|
|
|
|
|
|
const Register MathPowIntegerDescriptor::exponent() {
|
|
return MathPowTaggedDescriptor::exponent();
|
|
}
|
|
|
|
|
|
const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
|
|
const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
|
|
|
|
|
|
void StoreTransitionDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {ReceiverRegister(), NameRegister(), ValueRegister(),
|
|
MapRegister()};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void FastNewClosureDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void FastNewContextDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void TypeofDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ToNumberDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// ToNumberStub invokes a function, and therefore needs a context.
|
|
Register registers[] = {rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void NumberToStringDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax, rbx, rcx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax, rbx, rcx, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CreateAllocationSiteDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CreateWeakCellDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rbx, rdx, rdi};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void StoreArrayLiteralElementDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rcx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallFunctionDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallFunctionWithFeedbackDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi, rdx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallFunctionWithFeedbackAndVectorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdi, rdx, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallConstructDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// rax : number of arguments
|
|
// rbx : feedback vector
|
|
// rcx : original constructor (for IsSuperConstructorCall)
|
|
// rdx : slot in feedback vector (Smi, for RecordCallTarget)
|
|
// rdi : constructor function
|
|
// TODO(turbofan): So far we don't gather type feedback and hence skip the
|
|
// slot parameter, but ArrayConstructStub needs the vector to be undefined.
|
|
Register registers[] = {rax, rdi, rcx, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void RegExpConstructResultDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rcx, rbx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void TransitionElementsKindDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void AllocateHeapNumberDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
data->InitializePlatformSpecific(0, nullptr, nullptr);
|
|
}
|
|
|
|
|
|
void ArrayConstructorConstantArgCountDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// register state
|
|
// rax -- number of arguments
|
|
// rdi -- function
|
|
// rbx -- allocation site with elements kind
|
|
Register registers[] = {rdi, rbx};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ArrayConstructorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// stack param count needs (constructor pointer, and single argument)
|
|
Register registers[] = {rdi, rbx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void InternalArrayConstructorConstantArgCountDescriptor::
|
|
InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
|
|
// register state
|
|
// rax -- number of arguments
|
|
// rdi -- constructor function
|
|
Register registers[] = {rdi};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void InternalArrayConstructorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
// stack param count needs (constructor pointer, and single argument)
|
|
Register registers[] = {rdi, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CompareDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CompareNilDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ToBooleanDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void BinaryOpDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void BinaryOpWithAllocationSiteDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rcx, rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void StringAddDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {rdx, rax};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void KeyedDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rcx, // key
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void NamedDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rcx, // name
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void CallHandlerDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdx, // receiver
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ArgumentAdaptorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // JSFunction
|
|
rax, // actual number of arguments
|
|
rbx, // expected number of arguments
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ApiFunctionDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // callee
|
|
rbx, // call_data
|
|
rcx, // holder
|
|
rdx, // api_function_address
|
|
rax, // actual number of arguments
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void ApiAccessorDescriptor::InitializePlatformSpecific(
|
|
CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // callee
|
|
rbx, // call_data
|
|
rcx, // holder
|
|
rdx, // api_function_address
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void MathRoundVariantCallFromUnoptimizedCodeDescriptor::
|
|
InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // math rounding function
|
|
rdx, // vector slot id
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
|
|
|
|
void MathRoundVariantCallFromOptimizedCodeDescriptor::
|
|
InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
|
|
Register registers[] = {
|
|
rdi, // math rounding function
|
|
rdx, // vector slot id
|
|
rbx // type vector
|
|
};
|
|
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
}
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_TARGET_ARCH_X64
|