Commit 905e008c authored by mvstanton's avatar mvstanton Committed by Commit bot

Vector ICs: Hook up vectors in platform builtins to their SharedFunctionInfos.

BUG=v8:4423
LOG=N

Review URL: https://codereview.chromium.org/1342013003

Cr-Commit-Position: refs/heads/master@{#30758}
parent bf68348d
......@@ -1255,6 +1255,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
static void Generate_PushAppliedArguments(MacroAssembler* masm,
const int vectorOffset,
const int argumentsOffset,
const int indexOffset,
const int limitOffset) {
......@@ -1272,13 +1273,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm,
__ ldr(receiver, MemOperand(fp, argumentsOffset));
// Use inline caching to speed up access to arguments.
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
masm->isolate()->factory()->NewTypeFeedbackVector(&spec);
int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0));
__ mov(slot, Operand(Smi::FromInt(index)));
__ Move(vector, feedback_vector);
int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
__ mov(slot, Operand(Smi::FromInt(slot_index)));
__ ldr(vector, MemOperand(fp, vectorOffset));
Handle<Code> ic =
KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
__ Call(ic, RelocInfo::CODE_TARGET);
......@@ -1313,6 +1310,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
const int kReceiverOffset = kArgumentsOffset + kPointerSize;
const int kFunctionOffset = kReceiverOffset + kPointerSize;
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(r1);
__ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function
__ ldr(r1, MemOperand(fp, kArgumentsOffset)); // get the args array
......@@ -1327,17 +1331,15 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged);
// Push current limit and index.
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
__ mov(r1, Operand::Zero());
__ ldr(r2, MemOperand(fp, kReceiverOffset));
__ Push(r0, r1, r2); // limit, initial index and receiver.
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Call the callable.
// TODO(bmeurer): This should be a tail call according to ES6.
......@@ -1360,6 +1362,13 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
const int kFunctionOffset = kArgumentsOffset + kPointerSize;
static const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(r1);
// If newTarget is not supplied, set it to constructor
Label validate_arguments;
......@@ -1383,10 +1392,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
Generate_CheckStackOverflow(masm, kFunctionOffset, r0, kArgcIsSmiTagged);
// Push current limit and index.
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
__ push(r0); // limit
__ mov(r1, Operand::Zero()); // initial index
__ push(r1);
......@@ -1395,8 +1402,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
__ push(r0);
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(
masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Use undefined feedback vector
__ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
......
......@@ -1290,6 +1290,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
static void Generate_PushAppliedArguments(MacroAssembler* masm,
const int vectorOffset,
const int argumentsOffset,
const int indexOffset,
const int limitOffset) {
......@@ -1307,13 +1308,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm,
__ Ldr(receiver, MemOperand(fp, argumentsOffset));
// Use inline caching to speed up access to arguments.
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
masm->isolate()->factory()->NewTypeFeedbackVector(&spec);
int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0));
__ Mov(slot, Smi::FromInt(index));
__ Mov(vector, feedback_vector);
int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
__ Mov(slot, Operand(Smi::FromInt(slot_index)));
__ Ldr(vector, MemOperand(fp, vectorOffset));
Handle<Code> ic =
KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
__ Call(ic, RelocInfo::CODE_TARGET);
......@@ -1348,14 +1345,24 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
const int kReceiverOffset = kArgumentsOffset + kPointerSize;
const int kFunctionOffset = kReceiverOffset + kPointerSize;
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
Register args = x12;
Register receiver = x14;
Register function = x15;
Register apply_function = x1;
// Push the vector.
__ Ldr(
apply_function,
FieldMemOperand(apply_function, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(apply_function,
FieldMemOperand(apply_function,
SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(apply_function);
// Get the length of the arguments via a builtin call.
__ Ldr(function, MemOperand(fp, kFunctionOffset));
......@@ -1377,8 +1384,8 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
__ Push(argc, x1, receiver);
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// At the end of the loop, the number of arguments is stored in x0, untagged
......@@ -1402,16 +1409,25 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
const int kFunctionOffset = kArgumentsOffset + kPointerSize;
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
// Is x11 safe to use?
Register newTarget = x11;
Register args = x12;
Register function = x15;
Register construct_function = x1;
// Push the vector.
__ Ldr(construct_function,
FieldMemOperand(construct_function,
JSFunction::kSharedFunctionInfoOffset));
__ Ldr(construct_function,
FieldMemOperand(construct_function,
SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(construct_function);
// If newTarget is not supplied, set it to constructor
Label validate_arguments;
......@@ -1438,8 +1454,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
__ Push(argc, x1, function);
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(
masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Use undefined feedback vector
__ LoadRoot(x2, Heap::kUndefinedValueRootIndex);
......
......@@ -1796,6 +1796,8 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
MaybeHandle<JSObject>(), Builtins::kReflectApply);
apply->shared()->set_internal_formal_parameter_count(3);
apply->shared()->set_length(3);
apply->shared()->set_feedback_vector(
*TypeFeedbackVector::CreatePushAppliedArgumentsVector(isolate));
isolate->native_context()->set_reflect_apply(*apply);
Handle<JSFunction> construct = InstallFunction(
......@@ -1803,6 +1805,8 @@ void Bootstrapper::ExportFromRuntime(Isolate* isolate,
MaybeHandle<JSObject>(), Builtins::kReflectConstruct);
construct->shared()->set_internal_formal_parameter_count(3);
construct->shared()->set_length(2);
construct->shared()->set_feedback_vector(
*TypeFeedbackVector::CreatePushAppliedArgumentsVector(isolate));
isolate->native_context()->set_reflect_construct(*construct);
}
......@@ -2381,6 +2385,8 @@ bool Genesis::InstallNatives(ContextType context_type) {
Handle<JSFunction> apply =
InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
MaybeHandle<JSObject>(), Builtins::kFunctionApply);
apply->shared()->set_feedback_vector(
*TypeFeedbackVector::CreatePushAppliedArgumentsVector(isolate()));
// Make sure that Function.prototype.call appears to be compiled.
// The code will never be called, but inline caching for call will
......
......@@ -1004,6 +1004,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
static void Generate_PushAppliedArguments(MacroAssembler* masm,
const int vectorOffset,
const int argumentsOffset,
const int indexOffset,
const int limitOffset) {
......@@ -1019,13 +1020,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm,
__ mov(receiver, Operand(ebp, argumentsOffset)); // load arguments
// Use inline caching to speed up access to arguments.
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
masm->isolate()->factory()->NewTypeFeedbackVector(&spec);
int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0));
__ mov(slot, Immediate(Smi::FromInt(index)));
__ mov(vector, Immediate(feedback_vector));
int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
__ mov(slot, Immediate(Smi::FromInt(slot_index)));
__ mov(vector, Operand(ebp, vectorOffset));
Handle<Code> ic =
KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
__ call(ic, RelocInfo::CODE_TARGET);
......@@ -1073,6 +1070,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
static const int kFunctionOffset = kReceiverOffset + kPointerSize;
static const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset));
__ push(edi);
__ push(Operand(ebp, kFunctionOffset)); // push this
__ push(Operand(ebp, kArgumentsOffset)); // push arguments
......@@ -1086,16 +1090,15 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged);
// Push current index and limit.
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
__ Push(eax); // limit
__ Push(Immediate(0)); // index
__ Push(Operand(ebp, kReceiverOffset)); // receiver
// Loop over the arguments array, pushing each value to the stack
Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Call the callable.
// TODO(bmeurer): This should be a tail call according to ES6.
......@@ -1129,6 +1132,13 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
static const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
static const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ mov(edi, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(edi, FieldOperand(edi, SharedFunctionInfo::kFeedbackVectorOffset));
__ push(edi);
// If newTarget is not supplied, set it to constructor
Label validate_arguments;
......@@ -1149,8 +1159,7 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
Generate_CheckStackOverflow(masm, kFunctionOffset, kEaxIsSmiTagged);
// Push current index and limit.
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
__ Push(eax); // limit
__ push(Immediate(0)); // index
......@@ -1158,8 +1167,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
__ push(Operand(ebp, kFunctionOffset));
// Loop over the arguments array, pushing each value to the stack
Generate_PushAppliedArguments(
masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Use undefined feedback vector
__ LoadRoot(ebx, Heap::kUndefinedValueRootIndex);
......
......@@ -1253,6 +1253,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
static void Generate_PushAppliedArguments(MacroAssembler* masm,
const int vectorOffset,
const int argumentsOffset,
const int indexOffset,
const int limitOffset) {
......@@ -1270,13 +1271,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm,
__ lw(receiver, MemOperand(fp, argumentsOffset));
// Use inline caching to speed up access to arguments.
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
masm->isolate()->factory()->NewTypeFeedbackVector(&spec);
int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0));
__ li(slot, Operand(Smi::FromInt(index)));
__ li(vector, feedback_vector);
int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
__ li(slot, Operand(Smi::FromInt(slot_index)));
__ lw(vector, MemOperand(fp, vectorOffset));
Handle<Code> ic =
KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
__ Call(ic, RelocInfo::CODE_TARGET);
......@@ -1310,6 +1307,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
const int kReceiverOffset = kArgumentsOffset + kPointerSize;
const int kFunctionOffset = kReceiverOffset + kPointerSize;
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(a1);
__ lw(a0, MemOperand(fp, kFunctionOffset)); // Get the function.
__ lw(a1, MemOperand(fp, kArgumentsOffset)); // Get the args array.
......@@ -1326,17 +1330,15 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged);
// Push current limit and index.
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
__ mov(a1, zero_reg);
__ lw(a2, MemOperand(fp, kReceiverOffset));
__ Push(v0, a1, a2); // limit, initial index and receiver.
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Call the callable.
// TODO(bmeurer): This should be a tail call according to ES6.
......@@ -1360,6 +1362,13 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
const int kFunctionOffset = kArgumentsOffset + kPointerSize;
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ lw(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(a1);
// If newTarget is not supplied, set it to constructor
Label validate_arguments;
......@@ -1385,10 +1394,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged);
// Push current limit and index.
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
__ push(v0); // limit
__ mov(a1, zero_reg); // initial index
__ push(a1);
......@@ -1397,8 +1404,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
__ push(a0);
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(
masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Use undefined feedback vector
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
......
......@@ -1250,6 +1250,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
static void Generate_PushAppliedArguments(MacroAssembler* masm,
const int vectorOffset,
const int argumentsOffset,
const int indexOffset,
const int limitOffset) {
......@@ -1267,13 +1268,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm,
__ ld(receiver, MemOperand(fp, argumentsOffset));
// Use inline caching to speed up access to arguments.
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
masm->isolate()->factory()->NewTypeFeedbackVector(&spec);
int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0));
__ li(slot, Operand(Smi::FromInt(index)));
__ li(vector, feedback_vector);
int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
__ li(slot, Operand(Smi::FromInt(slot_index)));
__ ld(vector, MemOperand(fp, vectorOffset));
Handle<Code> ic =
KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
__ Call(ic, RelocInfo::CODE_TARGET);
......@@ -1307,6 +1304,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
const int kReceiverOffset = kArgumentsOffset + kPointerSize;
const int kFunctionOffset = kReceiverOffset + kPointerSize;
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ ld(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(a1);
__ ld(a0, MemOperand(fp, kFunctionOffset)); // Get the function.
__ ld(a1, MemOperand(fp, kArgumentsOffset)); // Get the args array.
......@@ -1324,17 +1328,15 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged);
// Push current limit and index.
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
__ mov(a1, zero_reg);
__ ld(a2, MemOperand(fp, kReceiverOffset));
__ Push(v0, a1, a2); // limit, initial index and receiver.
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Call the callable.
// TODO(bmeurer): This should be a tail call according to ES6.
......@@ -1358,6 +1360,13 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
const int kNewTargetOffset = kFPOnStackSize + kPCOnStackSize;
const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
const int kFunctionOffset = kArgumentsOffset + kPointerSize;
const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ ld(a1, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ ld(a1, FieldMemOperand(a1, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(a1);
// If newTarget is not supplied, set it to constructor
Label validate_arguments;
......@@ -1383,10 +1392,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
Generate_CheckStackOverflow(masm, kFunctionOffset, v0, kArgcIsSmiTagged);
// Push current limit and index.
const int kIndexOffset =
StandardFrameConstants::kExpressionsOffset - (2 * kPointerSize);
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - (1 * kPointerSize);
const int kIndexOffset = kVectorOffset - (2 * kPointerSize);
const int kLimitOffset = kVectorOffset - (1 * kPointerSize);
__ push(v0); // limit
__ mov(a1, zero_reg); // initial index
__ push(a1);
......@@ -1395,8 +1402,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
__ push(a0);
// Copy all arguments from the array to the stack.
Generate_PushAppliedArguments(
masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Use undefined feedback vector
__ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
......
......@@ -125,6 +125,26 @@ Handle<TypeFeedbackVector> TypeFeedbackVector::Allocate(Isolate* isolate,
}
// static
int TypeFeedbackVector::PushAppliedArgumentsIndex() {
const int index_count = VectorICComputer::word_count(1);
return kReservedIndexCount + index_count;
}
// static
Handle<TypeFeedbackVector> TypeFeedbackVector::CreatePushAppliedArgumentsVector(
Isolate* isolate) {
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
isolate->factory()->NewTypeFeedbackVector(&spec);
DCHECK(PushAppliedArgumentsIndex() ==
feedback_vector->GetIndex(FeedbackVectorICSlot(0)));
return feedback_vector;
}
// static
Handle<TypeFeedbackVector> TypeFeedbackVector::Copy(
Isolate* isolate, Handle<TypeFeedbackVector> vector) {
......
......@@ -181,6 +181,10 @@ class TypeFeedbackVector : public FixedArray {
return FeedbackVectorICSlot(dummyIndex);
}
static int PushAppliedArgumentsIndex();
static Handle<TypeFeedbackVector> CreatePushAppliedArgumentsVector(
Isolate* isolate);
private:
enum VectorICKind {
KindUnused = 0x0,
......
......@@ -1055,6 +1055,7 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
static void Generate_PushAppliedArguments(MacroAssembler* masm,
const int vectorOffset,
const int argumentsOffset,
const int indexOffset,
const int limitOffset) {
......@@ -1071,13 +1072,9 @@ static void Generate_PushAppliedArguments(MacroAssembler* masm,
__ movp(receiver, Operand(rbp, argumentsOffset)); // load arguments
// Use inline caching to speed up access to arguments.
Code::Kind kinds[] = {Code::KEYED_LOAD_IC};
FeedbackVectorSpec spec(0, 1, kinds);
Handle<TypeFeedbackVector> feedback_vector =
masm->isolate()->factory()->NewTypeFeedbackVector(&spec);
int index = feedback_vector->GetIndex(FeedbackVectorICSlot(0));
__ Move(slot, Smi::FromInt(index));
__ Move(vector, feedback_vector);
int slot_index = TypeFeedbackVector::PushAppliedArgumentsIndex();
__ Move(slot, Smi::FromInt(slot_index));
__ movp(vector, Operand(rbp, vectorOffset));
Handle<Code> ic =
KeyedLoadICStub(masm->isolate(), LoadICState(kNoExtraICState)).GetCode();
__ Call(ic, RelocInfo::CODE_TARGET);
......@@ -1124,6 +1121,13 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
static const int kArgumentsOffset = kFPOnStackSize + kPCOnStackSize;
static const int kReceiverOffset = kArgumentsOffset + kPointerSize;
static const int kFunctionOffset = kReceiverOffset + kPointerSize;
static const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ movp(rdi, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ movp(rdi, FieldOperand(rdi, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(rdi);
__ Push(Operand(rbp, kFunctionOffset));
__ Push(Operand(rbp, kArgumentsOffset));
......@@ -1137,16 +1141,15 @@ static void Generate_ApplyHelper(MacroAssembler* masm, bool targetIsArgument) {
Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged);
// Push current index and limit, and receiver.
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
__ Push(rax); // limit
__ Push(Immediate(0)); // index
__ Push(Operand(rbp, kReceiverOffset)); // receiver
// Loop over the arguments array, pushing each value to the stack
Generate_PushAppliedArguments(masm, kArgumentsOffset, kIndexOffset,
kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Call the callable.
// TODO(bmeurer): This should be a tail call according to ES6.
......@@ -1181,6 +1184,14 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
static const int kArgumentsOffset = kNewTargetOffset + kPointerSize;
static const int kFunctionOffset = kArgumentsOffset + kPointerSize;
static const int kVectorOffset =
InternalFrameConstants::kCodeOffset - 1 * kPointerSize;
// Push the vector.
__ movp(rdi, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ movp(rdi, FieldOperand(rdi, SharedFunctionInfo::kFeedbackVectorOffset));
__ Push(rdi);
// If newTarget is not supplied, set it to constructor
Label validate_arguments;
__ movp(rax, Operand(rbp, kNewTargetOffset));
......@@ -1200,8 +1211,7 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
Generate_CheckStackOverflow(masm, kFunctionOffset, kRaxIsSmiTagged);
// Push current index and limit.
const int kLimitOffset =
StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
const int kLimitOffset = kVectorOffset - 1 * kPointerSize;
const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
__ Push(rax); // limit
__ Push(Immediate(0)); // index
......@@ -1209,8 +1219,8 @@ static void Generate_ConstructHelper(MacroAssembler* masm) {
__ Push(Operand(rbp, kFunctionOffset));
// Loop over the arguments array, pushing each value to the stack
Generate_PushAppliedArguments(
masm, kArgumentsOffset, kIndexOffset, kLimitOffset);
Generate_PushAppliedArguments(masm, kVectorOffset, kArgumentsOffset,
kIndexOffset, kLimitOffset);
// Use undefined feedback vector
__ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
......
......@@ -3909,8 +3909,14 @@ static void CheckVectorIC(Handle<JSFunction> f, int ic_slot_index,
Handle<TypeFeedbackVector> vector =
Handle<TypeFeedbackVector>(f->shared()->feedback_vector());
FeedbackVectorICSlot slot(ic_slot_index);
if (vector->GetKind(slot) == Code::LOAD_IC) {
LoadICNexus nexus(vector, slot);
CHECK(nexus.StateFromFeedback() == desired_state);
} else {
CHECK(vector->GetKind(slot) == Code::KEYED_LOAD_IC);
KeyedLoadICNexus nexus(vector, slot);
CHECK(nexus.StateFromFeedback() == desired_state);
}
}
......@@ -3923,6 +3929,38 @@ static void CheckVectorICCleared(Handle<JSFunction> f, int ic_slot_index) {
}
TEST(ICInBuiltInIsClearedAppropriately) {
if (i::FLAG_always_opt) return;
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Handle<JSFunction> apply;
{
LocalContext env;
v8::Local<v8::Value> res = CompileRun("Function.apply");
Handle<JSObject> maybe_apply =
v8::Utils::OpenHandle(*v8::Handle<v8::Object>::Cast(res));
apply = Handle<JSFunction>::cast(maybe_apply);
TypeFeedbackVector* vector = apply->shared()->feedback_vector();
CHECK(vector->ICSlots() == 1);
CheckVectorIC(apply, 0, UNINITIALIZED);
CompileRun(
"function b(a1, a2, a3) { return a1 + a2 + a3; }"
"function fun(bar) { bar.apply({}, [1, 2, 3]); };"
"fun(b); fun(b)");
CheckVectorIC(apply, 0, MONOMORPHIC);
}
// Fire context dispose notification.
CcTest::isolate()->ContextDisposedNotification();
SimulateIncrementalMarking(CcTest::heap());
CcTest::heap()->CollectAllGarbage();
// The IC in apply has been cleared, ready to learn again.
CheckVectorIC(apply, 0, PREMONOMORPHIC);
}
TEST(IncrementalMarkingPreservesMonomorphicConstructor) {
if (i::FLAG_always_opt) return;
CcTest::InitializeVM();
......@@ -6524,9 +6562,12 @@ TEST(SharedFunctionInfoIterator) {
// Shared function infos without a script (API functions or C++ builtins)
// are not returned by the iterator because they are not created from a
// script. They are not interesting for type feedback vector anyways.
// TODO(mvstanton): There are builtins that use type feedback vectors,
// consider adding these to the iterator.
SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
if (shared->script()->IsUndefined()) {
CHECK_EQ(0, shared->feedback_vector()->ICSlots());
CHECK(shared->native() || 0 == shared->feedback_vector()->ICSlots());
} else {
sfi_count++;
}
......
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