mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 21:01:50 +00:00
Improve polymorphic inlining of int/int double/double operations.
I added inlining of the native Double methods _add, _sub, _mul and _div and fromInteger and unified the method recognition of the MethodRecognizer and the Intrinsifier classes. R=srdjan@google.com Review URL: https://codereview.chromium.org//484693003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@39446 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
8683cef7cc
commit
937726a0aa
|
@ -894,6 +894,37 @@ DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 4) {
|
|||
}
|
||||
|
||||
|
||||
// Handles a static call in unoptimized code that has one argument type not
|
||||
// seen before. Compile the target if necessary and update the ICData.
|
||||
// Arg0: argument.
|
||||
// Arg1: IC data object.
|
||||
DEFINE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg, 2) {
|
||||
const Instance& arg = Instance::CheckedHandle(arguments.ArgAt(0));
|
||||
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
|
||||
// IC data for static call is prepopulated with the statically known target.
|
||||
ASSERT(ic_data.NumberOfChecks() == 1);
|
||||
const Function& target = Function::Handle(ic_data.GetTargetAt(0));
|
||||
if (!target.HasCode()) {
|
||||
const Error& error = Error::Handle(Compiler::CompileFunction(isolate,
|
||||
target));
|
||||
if (!error.IsNull()) {
|
||||
Exceptions::PropagateError(error);
|
||||
}
|
||||
}
|
||||
ASSERT(!target.IsNull() && target.HasCode());
|
||||
ic_data.AddReceiverCheck(arg.GetClassId(), target, 1);
|
||||
if (FLAG_trace_ic) {
|
||||
DartFrameIterator iterator;
|
||||
StackFrame* caller_frame = iterator.NextFrame();
|
||||
ASSERT(caller_frame != NULL);
|
||||
OS::PrintErr("StaticCallMissHandler at %#" Px
|
||||
" target %s (%" Pd ")\n",
|
||||
caller_frame->pc(), target.ToCString(), arg.GetClassId());
|
||||
}
|
||||
arguments.SetReturn(target);
|
||||
}
|
||||
|
||||
|
||||
// Handles a static call in unoptimized code that has two argument types not
|
||||
// seen before. Compile the target if necessary and update the ICData.
|
||||
// Arg0: argument 0.
|
||||
|
|
|
@ -27,6 +27,7 @@ DECLARE_RUNTIME_ENTRY(FixCallersTarget);
|
|||
DECLARE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg);
|
||||
DECLARE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs);
|
||||
DECLARE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs);
|
||||
DECLARE_RUNTIME_ENTRY(StaticCallMissHandlerOneArg);
|
||||
DECLARE_RUNTIME_ENTRY(StaticCallMissHandlerTwoArgs);
|
||||
DECLARE_RUNTIME_ENTRY(Instanceof);
|
||||
DECLARE_RUNTIME_ENTRY(TypeCheck);
|
||||
|
|
|
@ -1296,15 +1296,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
|||
intptr_t token_pos,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data) {
|
||||
uword label_address = 0;
|
||||
StubCode* stub_code = isolate()->stub_code();
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = stub_code->ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = stub_code->TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
const uword label_address =
|
||||
stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
|
||||
ExternalLabel target_label(label_address);
|
||||
__ LoadObject(R5, ic_data);
|
||||
GenerateDartCall(deopt_id,
|
||||
|
|
|
@ -1301,15 +1301,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
|||
intptr_t token_pos,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data) {
|
||||
uword label_address = 0;
|
||||
StubCode* stub_code = isolate()->stub_code();
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = stub_code->ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = stub_code->TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
const uword label_address =
|
||||
stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
|
||||
ExternalLabel target_label(label_address);
|
||||
__ LoadObject(R5, ic_data, PP);
|
||||
GenerateDartCall(deopt_id,
|
||||
|
|
|
@ -1178,15 +1178,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
|||
intptr_t token_pos,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data) {
|
||||
uword label_address = 0;
|
||||
StubCode* stub_code = isolate()->stub_code();
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = stub_code->ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = stub_code->TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
const uword label_address =
|
||||
stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
|
||||
ExternalLabel target_label(label_address);
|
||||
__ LoadObject(ECX, ic_data);
|
||||
GenerateDartCall(deopt_id,
|
||||
|
|
|
@ -1337,15 +1337,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
|||
intptr_t token_pos,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data) {
|
||||
uword label_address = 0;
|
||||
StubCode* stub_code = isolate()->stub_code();
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = stub_code->ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = stub_code->TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
const uword label_address =
|
||||
stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
|
||||
ExternalLabel target_label(label_address);
|
||||
__ LoadObject(S5, ic_data);
|
||||
GenerateDartCall(deopt_id,
|
||||
|
|
|
@ -1215,15 +1215,9 @@ void FlowGraphCompiler::EmitUnoptimizedStaticCall(
|
|||
intptr_t token_pos,
|
||||
LocationSummary* locs,
|
||||
const ICData& ic_data) {
|
||||
uword label_address = 0;
|
||||
StubCode* stub_code = isolate()->stub_code();
|
||||
if (ic_data.NumArgsTested() == 0) {
|
||||
label_address = stub_code->ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else if (ic_data.NumArgsTested() == 2) {
|
||||
label_address = stub_code->TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
const uword label_address =
|
||||
stub_code->UnoptimizedStaticCallEntryPoint(ic_data.NumArgsTested());
|
||||
ExternalLabel target_label(label_address);
|
||||
__ LoadObject(RBX, ic_data, PP);
|
||||
GenerateDartCall(deopt_id,
|
||||
|
|
|
@ -1560,6 +1560,14 @@ bool FlowGraphOptimizer::TryInlineRecognizedMethod(intptr_t receiver_cid,
|
|||
return InlineStringCodeUnitAt(call, receiver_cid, entry, last);
|
||||
case MethodRecognizer::kStringBaseCharAt:
|
||||
return InlineStringBaseCharAt(call, receiver_cid, entry, last);
|
||||
case MethodRecognizer::kDoubleAdd:
|
||||
return InlineDoubleOp(Token::kADD, call, entry, last);
|
||||
case MethodRecognizer::kDoubleSub:
|
||||
return InlineDoubleOp(Token::kSUB, call, entry, last);
|
||||
case MethodRecognizer::kDoubleMul:
|
||||
return InlineDoubleOp(Token::kMUL, call, entry, last);
|
||||
case MethodRecognizer::kDoubleDiv:
|
||||
return InlineDoubleOp(Token::kDIV, call, entry, last);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -2336,21 +2344,6 @@ void FlowGraphOptimizer::InlineImplicitInstanceGetter(InstanceCallInstr* call) {
|
|||
}
|
||||
|
||||
|
||||
LoadFieldInstr* FlowGraphOptimizer::BuildLoadStringLength(Definition* str) {
|
||||
// Treat length loads as mutable (i.e. affected by side effects) to avoid
|
||||
// hoisting them since we can't hoist the preceding class-check. This
|
||||
// is because of externalization of strings that affects their class-id.
|
||||
LoadFieldInstr* load = new(I) LoadFieldInstr(
|
||||
new(I) Value(str),
|
||||
String::length_offset(),
|
||||
Type::ZoneHandle(I, Type::SmiType()),
|
||||
str->token_pos());
|
||||
load->set_result_cid(kSmiCid);
|
||||
load->set_recognized_kind(MethodRecognizer::kStringBaseLength);
|
||||
return load;
|
||||
}
|
||||
|
||||
|
||||
bool FlowGraphOptimizer::InlineFloat32x4Getter(InstanceCallInstr* call,
|
||||
MethodRecognizer::Kind getter) {
|
||||
if (!ShouldInlineSimd()) {
|
||||
|
@ -2711,7 +2704,17 @@ Definition* FlowGraphOptimizer::PrepareInlineStringIndexOp(
|
|||
FlowGraph::kEffect);
|
||||
|
||||
// Load the length of the string.
|
||||
LoadFieldInstr* length = BuildLoadStringLength(str);
|
||||
// Treat length loads as mutable (i.e. affected by side effects) to avoid
|
||||
// hoisting them since we can't hoist the preceding class-check. This
|
||||
// is because of externalization of strings that affects their class-id.
|
||||
LoadFieldInstr* length = new(I) LoadFieldInstr(
|
||||
new(I) Value(str),
|
||||
String::length_offset(),
|
||||
Type::ZoneHandle(I, Type::SmiType()),
|
||||
str->token_pos());
|
||||
length->set_result_cid(kSmiCid);
|
||||
length->set_recognized_kind(MethodRecognizer::kStringBaseLength);
|
||||
|
||||
cursor = flow_graph()->AppendTo(cursor, length, NULL, FlowGraph::kValue);
|
||||
// Bounds check.
|
||||
cursor = flow_graph()->AppendTo(cursor,
|
||||
|
@ -2790,6 +2793,30 @@ bool FlowGraphOptimizer::InlineStringBaseCharAt(
|
|||
}
|
||||
|
||||
|
||||
bool FlowGraphOptimizer::InlineDoubleOp(
|
||||
Token::Kind op_kind,
|
||||
Instruction* call,
|
||||
TargetEntryInstr** entry,
|
||||
Definition** last) {
|
||||
Definition* left = call->ArgumentAt(0);
|
||||
Definition* right = call->ArgumentAt(1);
|
||||
|
||||
*entry = new(I) TargetEntryInstr(flow_graph()->allocate_block_id(),
|
||||
call->GetBlock()->try_index());
|
||||
(*entry)->InheritDeoptTarget(I, call);
|
||||
// Arguments are checked. No need for class check.
|
||||
BinaryDoubleOpInstr* double_bin_op =
|
||||
new(I) BinaryDoubleOpInstr(op_kind,
|
||||
new(I) Value(left),
|
||||
new(I) Value(right),
|
||||
call->deopt_id(), call->token_pos());
|
||||
flow_graph()->AppendTo(*entry, double_bin_op, call->env(), FlowGraph::kValue);
|
||||
*last = double_bin_op;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FlowGraphOptimizer::ReplaceWithMathCFunction(
|
||||
InstanceCallInstr* call,
|
||||
MethodRecognizer::Kind recognized_kind) {
|
||||
|
@ -2960,6 +2987,11 @@ bool FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallInstr* call) {
|
|||
ReplaceCall(call, d2d_instr);
|
||||
}
|
||||
return true;
|
||||
case MethodRecognizer::kDoubleAdd:
|
||||
case MethodRecognizer::kDoubleSub:
|
||||
case MethodRecognizer::kDoubleMul:
|
||||
case MethodRecognizer::kDoubleDiv:
|
||||
return TryReplaceInstanceCallWithInline(call);
|
||||
default:
|
||||
// Unsupported method.
|
||||
return false;
|
||||
|
@ -4342,6 +4374,23 @@ void FlowGraphOptimizer::VisitStaticCall(StaticCallInstr* call) {
|
|||
CreateArrayInstr* create_array =
|
||||
new(I) CreateArrayInstr(call->token_pos(), type, num_elements);
|
||||
ReplaceCall(call, create_array);
|
||||
} else if (recognized_kind == MethodRecognizer::kDoubleFromInteger) {
|
||||
if (call->HasICData() && (call->ic_data()->NumberOfChecks() == 1)) {
|
||||
const ICData& ic_data = *call->ic_data();
|
||||
if (CanUnboxDouble() && ArgIsAlways(kSmiCid, ic_data, 0)) {
|
||||
Definition* arg = call->ArgumentAt(0);
|
||||
InsertBefore(call,
|
||||
new(I) CheckSmiInstr(
|
||||
new(I) Value(arg),
|
||||
call->deopt_id(),
|
||||
call->token_pos()),
|
||||
call->env(),
|
||||
FlowGraph::kEffect);
|
||||
ReplaceCall(call,
|
||||
new(I) SmiToDoubleInstr(new(I) Value(arg),
|
||||
call->token_pos()));
|
||||
}
|
||||
}
|
||||
} else if (call->function().IsFactory()) {
|
||||
const Class& function_class =
|
||||
Class::Handle(I, call->function().Owner());
|
||||
|
|
|
@ -131,8 +131,6 @@ class FlowGraphOptimizer : public FlowGraphVisitor {
|
|||
|
||||
bool TryReplaceInstanceCallWithInline(InstanceCallInstr* call);
|
||||
|
||||
LoadFieldInstr* BuildLoadStringLength(Definition* str);
|
||||
|
||||
Definition* PrepareInlineStringIndexOp(Instruction* call,
|
||||
intptr_t cid,
|
||||
Definition* str,
|
||||
|
@ -149,6 +147,11 @@ class FlowGraphOptimizer : public FlowGraphVisitor {
|
|||
TargetEntryInstr** entry,
|
||||
Definition** last);
|
||||
|
||||
bool InlineDoubleOp(Token::Kind op_kind,
|
||||
Instruction* call,
|
||||
TargetEntryInstr** entry,
|
||||
Definition** last);
|
||||
|
||||
bool InlineByteArrayViewLoad(Instruction* call,
|
||||
Definition* receiver,
|
||||
intptr_t array_cid,
|
||||
|
|
|
@ -2312,9 +2312,16 @@ void StaticCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
MethodRecognizer::Kind recognized_kind =
|
||||
MethodRecognizer::RecognizeKind(function());
|
||||
int num_args_checked = 0;
|
||||
if ((recognized_kind == MethodRecognizer::kMathMin) ||
|
||||
(recognized_kind == MethodRecognizer::kMathMax)) {
|
||||
num_args_checked = 2;
|
||||
switch (recognized_kind) {
|
||||
case MethodRecognizer::kDoubleFromInteger:
|
||||
num_args_checked = 1;
|
||||
break;
|
||||
case MethodRecognizer::kMathMin:
|
||||
case MethodRecognizer::kMathMax:
|
||||
num_args_checked = 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
call_ic_data = compiler->GetOrAddStaticCallICData(deopt_id(),
|
||||
function(),
|
||||
|
|
|
@ -42,11 +42,16 @@ namespace dart {
|
|||
V(_IntegerImplementation, toDouble, IntegerToDouble, 1084977108) \
|
||||
V(_IntegerImplementation, _leftShiftWithMask32, IntegerLeftShiftWithMask32, \
|
||||
597111055) \
|
||||
V(_Double, .fromInteger, DoubleFromInteger, 999771940) \
|
||||
V(_Double, truncateToDouble, DoubleTruncate, 2117801967) \
|
||||
V(_Double, roundToDouble, DoubleRound, 2124216110) \
|
||||
V(_Double, floorToDouble, DoubleFloor, 968600699) \
|
||||
V(_Double, ceilToDouble, DoubleCeil, 1779929274) \
|
||||
V(_Double, _modulo, DoubleMod, 1473971007) \
|
||||
V(_Double, _add, DoubleAdd, 1570715125) \
|
||||
V(_Double, _sub, DoubleSub, 1466395310) \
|
||||
V(_Double, _mul, DoubleMul, 546441193) \
|
||||
V(_Double, _div, DoubleDiv, 1201505037) \
|
||||
V(::, sin, MathSin, 1741396147) \
|
||||
V(::, cos, MathCos, 1951197905) \
|
||||
V(::, min, MathMin, 1022567780) \
|
||||
|
|
|
@ -11351,11 +11351,15 @@ void ICData::AddTarget(const Function& target) const {
|
|||
ASSERT(!target.IsNull());
|
||||
if (NumArgsTested() > 0) {
|
||||
// Create a fake cid entry, so that we can store the target.
|
||||
GrowableArray<intptr_t> class_ids(NumArgsTested());
|
||||
for (intptr_t i = 0; i < NumArgsTested(); i++) {
|
||||
class_ids.Add(kObjectCid);
|
||||
if (NumArgsTested() == 1) {
|
||||
AddReceiverCheck(kObjectCid, target, 1);
|
||||
} else {
|
||||
GrowableArray<intptr_t> class_ids(NumArgsTested());
|
||||
for (intptr_t i = 0; i < NumArgsTested(); i++) {
|
||||
class_ids.Add(kObjectCid);
|
||||
}
|
||||
AddCheck(class_ids, target);
|
||||
}
|
||||
AddCheck(class_ids, target);
|
||||
return;
|
||||
}
|
||||
ASSERT(NumArgsTested() >= 0);
|
||||
|
|
|
@ -133,6 +133,21 @@ RawCode* StubCode::GetAllocationStubForClass(const Class& cls) {
|
|||
}
|
||||
|
||||
|
||||
uword StubCode::UnoptimizedStaticCallEntryPoint(intptr_t num_args_tested) {
|
||||
switch (num_args_tested) {
|
||||
case 0:
|
||||
return ZeroArgsUnoptimizedStaticCallEntryPoint();
|
||||
case 1:
|
||||
return OneArgUnoptimizedStaticCallEntryPoint();
|
||||
case 2:
|
||||
return TwoArgsUnoptimizedStaticCallEntryPoint();
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RawCode* StubCode::Generate(const char* name,
|
||||
void (*GenerateStub)(Assembler* assembler)) {
|
||||
Assembler assembler;
|
||||
|
|
|
@ -62,6 +62,7 @@ class RawCode;
|
|||
V(ThreeArgsOptimizedCheckInlineCache) \
|
||||
V(ClosureCallInlineCache) \
|
||||
V(ZeroArgsUnoptimizedStaticCall) \
|
||||
V(OneArgUnoptimizedStaticCall) \
|
||||
V(TwoArgsUnoptimizedStaticCall) \
|
||||
V(OptimizeFunction) \
|
||||
V(InvokeDartCode) \
|
||||
|
@ -162,6 +163,8 @@ class StubCode {
|
|||
|
||||
static RawCode* GetAllocationStubForClass(const Class& cls);
|
||||
|
||||
uword UnoptimizedStaticCallEntryPoint(intptr_t num_args_tested);
|
||||
|
||||
static const intptr_t kNoInstantiator = 0;
|
||||
|
||||
private:
|
||||
|
|
|
@ -1494,6 +1494,13 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, R6);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry);
|
||||
}
|
||||
|
||||
|
||||
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, R6);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
|
|
|
@ -1602,6 +1602,13 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, R6);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry);
|
||||
}
|
||||
|
||||
|
||||
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, R6);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
|
|
|
@ -1552,6 +1552,13 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, EBX);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry);
|
||||
}
|
||||
|
||||
|
||||
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, EBX);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
|
|
|
@ -1686,6 +1686,13 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, T0);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry);
|
||||
}
|
||||
|
||||
|
||||
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, T0);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
|
|
|
@ -1518,6 +1518,13 @@ void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, RCX);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry);
|
||||
}
|
||||
|
||||
|
||||
void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
|
||||
GenerateUsageCounterIncrement(assembler, RCX);
|
||||
GenerateNArgsCheckInlineCacheStub(
|
||||
|
|
Loading…
Reference in a new issue