mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 15:57:17 +00:00
Reland "[vm] Replace array GetIndexed graph intrinsics with flow graph builder implementation"
This is a reland of commit d24b5d1f5e
On top of the original change, the following is fixed and improved:
1) Flow graph builder (FGB) body is now also applied to
dynamic invocation forwarders (similarly to graph
intrinsics).
2) Frame can be omitted for functions which have a
call on a shared slow path. This is needed to make
FGB implementation of GetIndexed frameless, as it has
GenericCheckBound which calls on shared slow path.
(Graph intrinsics are frameless).
3) Range analysis is enabled for force-optimized functions,
so more efficient code can be generated for boxing
instructions. Range analysis is fixed to avoid crashes
and correctly intersect ranges with constant boundaries
(needed for some force-optimized FFI functions).
4) EliminateStackOverflowChecks pass is enabled for
force-optimized functions so CheckStackOverflow can be
eliminated.
Original change's description:
> [vm] Replace array GetIndexed graph intrinsics with flow graph builder implementation
>
> _Array, _GrowableList, internal and external typed data 'operator []'
> are now implemented in the flow graph builder.
>
> Unlike graph intrinsics, flow graph created in the flow graph builder
> can be used by the inliner. Corresponding graph intrinsics and native
> methods are removed.
>
> Also, this change adds missing external typed data indexing operations.
>
> TEST=ci
>
> Change-Id: Ic19784481feadf54c096a587413e67b4e18353dc
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/359940
> Reviewed-by: Ryan Macnak <rmacnak@google.com>
> Commit-Queue: Alexander Markov <alexmarkov@google.com>
TEST=ci
Change-Id: I04ef008a04238d432683d7543cd047e35bad17c3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/360560
Reviewed-by: Tess Strickland <sstrickl@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
parent
df1361dded
commit
0af6dde79d
|
@ -16,15 +16,6 @@ DEFINE_NATIVE_ENTRY(List_allocate, 0, 2) {
|
|||
return Object::null();
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(List_getIndexed, 0, 2) {
|
||||
const Array& array = Array::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
|
||||
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
|
||||
Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
|
||||
}
|
||||
return array.At(index.Value());
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(List_setIndexed, 0, 3) {
|
||||
const Array& array = Array::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
|
||||
|
|
|
@ -28,17 +28,6 @@ DEFINE_NATIVE_ENTRY(GrowableList_allocate, 0, 2) {
|
|||
return new_array.ptr();
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(GrowableList_getIndexed, 0, 2) {
|
||||
const GrowableObjectArray& array =
|
||||
GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1));
|
||||
if ((index.Value() < 0) || (index.Value() >= array.Length())) {
|
||||
Exceptions::ThrowRangeError("index", index, 0, array.Length() - 1);
|
||||
}
|
||||
const Instance& obj = Instance::CheckedHandle(zone, array.At(index.Value()));
|
||||
return obj.ptr();
|
||||
}
|
||||
|
||||
DEFINE_NATIVE_ENTRY(GrowableList_setIndexed, 0, 3) {
|
||||
const GrowableObjectArray& array =
|
||||
GrowableObjectArray::CheckedHandle(zone, arguments->NativeArgAt(0));
|
||||
|
|
|
@ -119,7 +119,6 @@ namespace dart {
|
|||
V(RegExp_ExecuteMatch, 3) \
|
||||
V(RegExp_ExecuteMatchSticky, 3) \
|
||||
V(List_allocate, 2) \
|
||||
V(List_getIndexed, 2) \
|
||||
V(List_setIndexed, 3) \
|
||||
V(List_getLength, 1) \
|
||||
V(List_slice, 4) \
|
||||
|
@ -264,7 +263,6 @@ namespace dart {
|
|||
V(Isolate_spawnFunction, 10) \
|
||||
V(Isolate_spawnUri, 12) \
|
||||
V(GrowableList_allocate, 2) \
|
||||
V(GrowableList_getIndexed, 2) \
|
||||
V(GrowableList_setIndexed, 3) \
|
||||
V(GrowableList_getLength, 1) \
|
||||
V(GrowableList_getCapacity, 1) \
|
||||
|
|
|
@ -3060,10 +3060,25 @@ void ThrowErrorSlowPathCode::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
__ Bind(entry_label());
|
||||
EmitCodeAtSlowPathEntry(compiler);
|
||||
LocationSummary* locs = instruction()->locs();
|
||||
// Save registers as they are needed for lazy deopt / exception handling.
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (use_shared_stub) {
|
||||
if (!has_frame) {
|
||||
#if !defined(TARGET_ARCH_IA32)
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
#endif
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
EmitSharedStubCall(compiler, live_fpu_registers);
|
||||
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
|
||||
if (!has_frame) {
|
||||
// Undo EnterDartFrame for the code generated after this slow path.
|
||||
RESTORES_LR_FROM_FRAME({});
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ASSERT(has_frame);
|
||||
// Save registers as they are needed for lazy deopt / exception handling.
|
||||
compiler->SaveLiveRegisters(locs);
|
||||
PushArgumentsForRuntimeCall(compiler);
|
||||
__ CallRuntime(runtime_entry_, num_args);
|
||||
|
|
|
@ -3375,7 +3375,13 @@ class CheckStackOverflowSlowPath
|
|||
compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs);
|
||||
compiler->pending_deoptimization_env_ = env;
|
||||
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (using_shared_stub) {
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
const uword entry_point_offset = compiler::target::Thread::
|
||||
stack_overflow_shared_stub_entry_point_offset(
|
||||
instruction()->locs()->live_registers()->FpuRegisterCount() > 0);
|
||||
|
@ -3385,7 +3391,12 @@ class CheckStackOverflowSlowPath
|
|||
compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOther,
|
||||
instruction()->deopt_id(),
|
||||
instruction()->source());
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
ASSERT(has_frame);
|
||||
__ CallRuntime(kInterruptOrStackOverflowRuntimeEntry, kNumSlowPathArgs);
|
||||
compiler->EmitCallsiteMetadata(
|
||||
instruction()->source(), instruction()->deopt_id(),
|
||||
|
@ -3428,7 +3439,8 @@ void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
? object_store->stack_overflow_stub_with_fpu_regs_stub()
|
||||
: object_store->stack_overflow_stub_without_fpu_regs_stub());
|
||||
const bool using_shared_stub = locs()->call_on_shared_slow_path();
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub)) {
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub) &&
|
||||
compiler->flow_graph().graph_entry()->NeedsFrame()) {
|
||||
__ GenerateUnRelocatedPcRelativeCall(LS);
|
||||
compiler->AddPcRelativeCallStubTarget(stub);
|
||||
|
||||
|
@ -4540,6 +4552,12 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->intrinsic_slow_path_label(),
|
||||
compiler::Assembler::kNearJump, out_reg, tmp);
|
||||
} else if (locs()->call_on_shared_slow_path()) {
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
|
@ -4552,6 +4570,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
locs(), DeoptId::kNone, extended_env);
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
|
||||
out_reg, tmp);
|
||||
|
@ -6290,7 +6312,8 @@ void CheckNullInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
NullErrorSlowPath::GetStub(compiler, exception_type(), live_fpu_regs));
|
||||
const bool using_shared_stub = locs()->call_on_shared_slow_path();
|
||||
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub)) {
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub) &&
|
||||
compiler->flow_graph().graph_entry()->NeedsFrame()) {
|
||||
__ GenerateUnRelocatedPcRelativeCall(EQUAL);
|
||||
compiler->AddPcRelativeCallStubTarget(stub);
|
||||
|
||||
|
|
|
@ -2935,7 +2935,13 @@ class CheckStackOverflowSlowPath
|
|||
compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs);
|
||||
compiler->pending_deoptimization_env_ = env;
|
||||
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (using_shared_stub) {
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
|
@ -2944,7 +2950,7 @@ class CheckStackOverflowSlowPath
|
|||
? object_store->stack_overflow_stub_with_fpu_regs_stub()
|
||||
: object_store->stack_overflow_stub_without_fpu_regs_stub());
|
||||
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub)) {
|
||||
if (compiler->CanPcRelativeCall(stub)) {
|
||||
__ GenerateUnRelocatedPcRelativeCall();
|
||||
compiler->AddPcRelativeCallStubTarget(stub);
|
||||
} else {
|
||||
|
@ -2958,7 +2964,12 @@ class CheckStackOverflowSlowPath
|
|||
compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOther,
|
||||
instruction()->deopt_id(),
|
||||
instruction()->source());
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
ASSERT(has_frame);
|
||||
__ CallRuntime(kInterruptOrStackOverflowRuntimeEntry, kNumSlowPathArgs);
|
||||
compiler->EmitCallsiteMetadata(
|
||||
instruction()->source(), instruction()->deopt_id(),
|
||||
|
@ -3775,6 +3786,12 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->intrinsic_slow_path_label(),
|
||||
compiler::Assembler::kNearJump, out, temp);
|
||||
} else if (locs()->call_on_shared_slow_path()) {
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
|
@ -3787,6 +3804,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
locs(), DeoptId::kNone, extended_env);
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
|
||||
temp);
|
||||
|
|
|
@ -3182,7 +3182,13 @@ class CheckStackOverflowSlowPath
|
|||
compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs);
|
||||
compiler->pending_deoptimization_env_ = env;
|
||||
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (using_shared_stub) {
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
|
@ -3191,7 +3197,7 @@ class CheckStackOverflowSlowPath
|
|||
? object_store->stack_overflow_stub_with_fpu_regs_stub()
|
||||
: object_store->stack_overflow_stub_without_fpu_regs_stub());
|
||||
|
||||
if (using_shared_stub && compiler->CanPcRelativeCall(stub)) {
|
||||
if (compiler->CanPcRelativeCall(stub)) {
|
||||
__ GenerateUnRelocatedPcRelativeCall();
|
||||
compiler->AddPcRelativeCallStubTarget(stub);
|
||||
} else {
|
||||
|
@ -3205,7 +3211,12 @@ class CheckStackOverflowSlowPath
|
|||
compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOther,
|
||||
instruction()->deopt_id(),
|
||||
instruction()->source());
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
ASSERT(has_frame);
|
||||
__ CallRuntime(kInterruptOrStackOverflowRuntimeEntry, kNumSlowPathArgs);
|
||||
compiler->EmitCallsiteMetadata(
|
||||
instruction()->source(), instruction()->deopt_id(),
|
||||
|
@ -4140,6 +4151,12 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->intrinsic_slow_path_label(),
|
||||
compiler::Assembler::kNearJump, out_reg, TMP);
|
||||
} else if (locs()->call_on_shared_slow_path()) {
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
|
@ -4152,6 +4169,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
locs(), DeoptId::kNone, extended_env);
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(),
|
||||
out_reg, TMP);
|
||||
|
|
|
@ -2964,7 +2964,13 @@ class CheckStackOverflowSlowPath
|
|||
compiler->SlowPathEnvironmentFor(instruction(), kNumSlowPathArgs);
|
||||
compiler->pending_deoptimization_env_ = env;
|
||||
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (using_shared_stub) {
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
const uword entry_point_offset =
|
||||
Thread::stack_overflow_shared_stub_entry_point_offset(
|
||||
instruction()->locs()->live_registers()->FpuRegisterCount() > 0);
|
||||
|
@ -2974,7 +2980,12 @@ class CheckStackOverflowSlowPath
|
|||
compiler->AddCurrentDescriptor(UntaggedPcDescriptors::kOther,
|
||||
instruction()->deopt_id(),
|
||||
instruction()->source());
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
ASSERT(has_frame);
|
||||
__ CallRuntime(kInterruptOrStackOverflowRuntimeEntry, kNumSlowPathArgs);
|
||||
compiler->EmitCallsiteMetadata(
|
||||
instruction()->source(), instruction()->deopt_id(),
|
||||
|
@ -4103,6 +4114,12 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
compiler->intrinsic_slow_path_label(),
|
||||
compiler::Assembler::kNearJump, out, temp);
|
||||
} else if (locs()->call_on_shared_slow_path()) {
|
||||
const bool has_frame = compiler->flow_graph().graph_entry()->NeedsFrame();
|
||||
if (!has_frame) {
|
||||
ASSERT(__ constant_pool_allowed());
|
||||
__ set_constant_pool_allowed(false);
|
||||
__ EnterDartFrame(0);
|
||||
}
|
||||
auto object_store = compiler->isolate_group()->object_store();
|
||||
const bool live_fpu_regs = locs()->live_registers()->FpuRegisterCount() > 0;
|
||||
const auto& stub = Code::ZoneHandle(
|
||||
|
@ -4115,6 +4132,10 @@ void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
|
|||
auto extended_env = compiler->SlowPathEnvironmentFor(this, 0);
|
||||
compiler->GenerateStubCall(source(), stub, UntaggedPcDescriptors::kOther,
|
||||
locs(), DeoptId::kNone, extended_env);
|
||||
if (!has_frame) {
|
||||
__ LeaveDartFrame();
|
||||
__ set_constant_pool_allowed(true);
|
||||
}
|
||||
} else {
|
||||
BoxAllocationSlowPath::Allocate(compiler, this, compiler->mint_class(), out,
|
||||
temp);
|
||||
|
|
|
@ -3258,11 +3258,21 @@ void FlowGraphAllocator::RemoveFrameIfNotNeeded() {
|
|||
#if defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_ARM)
|
||||
bool has_write_barrier_call = false;
|
||||
#endif
|
||||
intptr_t num_calls_on_shared_slow_path = 0;
|
||||
for (auto block : block_order_) {
|
||||
for (auto instruction : block->instructions()) {
|
||||
if (instruction->HasLocs() && instruction->locs()->can_call()) {
|
||||
// Function contains a call and thus needs a frame.
|
||||
return;
|
||||
if (!instruction->locs()->call_on_shared_slow_path()) {
|
||||
// Function contains a call and thus needs a frame.
|
||||
return;
|
||||
}
|
||||
// For calls on shared slow paths the frame can be created on
|
||||
// a slow path around the call. Only allow one call on a shared
|
||||
// slow path to avoid extra code size.
|
||||
++num_calls_on_shared_slow_path;
|
||||
if (num_calls_on_shared_slow_path > 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Some instructions contain write barriers inside, which can call
|
||||
|
|
|
@ -2054,6 +2054,10 @@ RangeBoundary RangeBoundary::IntersectionMin(RangeBoundary a, RangeBoundary b) {
|
|||
return a;
|
||||
}
|
||||
|
||||
if (a.IsConstant() && b.IsConstant()) {
|
||||
return RangeBoundary(Utils::Maximum(a.ConstantValue(), b.ConstantValue()));
|
||||
}
|
||||
|
||||
if (a.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) {
|
||||
return b;
|
||||
} else if (b.IsMinimumOrBelow(RangeBoundary::kRangeBoundarySmi)) {
|
||||
|
@ -2079,6 +2083,10 @@ RangeBoundary RangeBoundary::IntersectionMax(RangeBoundary a, RangeBoundary b) {
|
|||
return a;
|
||||
}
|
||||
|
||||
if (a.IsConstant() && b.IsConstant()) {
|
||||
return RangeBoundary(Utils::Minimum(a.ConstantValue(), b.ConstantValue()));
|
||||
}
|
||||
|
||||
if (a.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) {
|
||||
return b;
|
||||
} else if (b.IsMaximumOrAbove(RangeBoundary::kRangeBoundarySmi)) {
|
||||
|
|
|
@ -320,6 +320,7 @@ FlowGraph* CompilerPass::RunForceOptimizedPipeline(
|
|||
INVOKE_PASS(SelectRepresentations_Final);
|
||||
INVOKE_PASS(CSE);
|
||||
INVOKE_PASS(TypePropagation);
|
||||
INVOKE_PASS(RangeAnalysis);
|
||||
INVOKE_PASS(TryCatchOptimization);
|
||||
INVOKE_PASS(EliminateEnvironments);
|
||||
INVOKE_PASS(EliminateDeadPhis);
|
||||
|
@ -328,6 +329,7 @@ FlowGraph* CompilerPass::RunForceOptimizedPipeline(
|
|||
INVOKE_PASS(DCE);
|
||||
INVOKE_PASS(Canonicalize);
|
||||
INVOKE_PASS_AOT(DelayAllocations);
|
||||
INVOKE_PASS(EliminateStackOverflowChecks);
|
||||
INVOKE_PASS(EliminateWriteBarriers);
|
||||
// This must be done after all other possible intra-block code motion.
|
||||
INVOKE_PASS(LoweringAfterCodeMotionDisabled);
|
||||
|
|
|
@ -868,6 +868,39 @@ Fragment FlowGraphBuilder::NativeFunctionBody(const Function& function,
|
|||
return body;
|
||||
}
|
||||
|
||||
static bool CanUnboxElements(classid_t cid) {
|
||||
switch (RepresentationUtils::RepresentationOfArrayElement(cid)) {
|
||||
case kUnboxedFloat:
|
||||
case kUnboxedDouble:
|
||||
return FlowGraphCompiler::SupportsUnboxedDoubles();
|
||||
case kUnboxedInt32x4:
|
||||
case kUnboxedFloat32x4:
|
||||
case kUnboxedFloat64x2:
|
||||
return FlowGraphCompiler::SupportsUnboxedSimd128();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const Function& TypedListGetNativeFunction(Thread* thread, classid_t cid) {
|
||||
auto& state = thread->compiler_state();
|
||||
switch (RepresentationUtils::RepresentationOfArrayElement(cid)) {
|
||||
case kUnboxedFloat:
|
||||
return state.TypedListGetFloat32();
|
||||
case kUnboxedDouble:
|
||||
return state.TypedListGetFloat64();
|
||||
case kUnboxedInt32x4:
|
||||
return state.TypedListGetInt32x4();
|
||||
case kUnboxedFloat32x4:
|
||||
return state.TypedListGetFloat32x4();
|
||||
case kUnboxedFloat64x2:
|
||||
return state.TypedListGetFloat64x2();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Object::null_function();
|
||||
}
|
||||
}
|
||||
|
||||
#define LOAD_NATIVE_FIELD(V) \
|
||||
V(ByteDataViewLength, TypedDataBase_length) \
|
||||
V(ByteDataViewOffsetInBytes, TypedDataView_offset_in_bytes) \
|
||||
|
@ -928,6 +961,36 @@ bool FlowGraphBuilder::IsRecognizedMethodForFlowGraph(
|
|||
const MethodRecognizer::Kind kind = function.recognized_kind();
|
||||
|
||||
switch (kind) {
|
||||
case MethodRecognizer::kObjectArrayGetIndexed:
|
||||
case MethodRecognizer::kGrowableArrayGetIndexed:
|
||||
case MethodRecognizer::kInt8ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt8ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint8ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint8ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint8ClampedArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
|
||||
case MethodRecognizer::kInt16ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt16ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint16ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint16ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt32ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint32ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt64ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint64ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat32ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat64ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat64x2ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat64x2ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kRecord_fieldAt:
|
||||
case MethodRecognizer::kRecord_fieldNames:
|
||||
case MethodRecognizer::kRecord_numFields:
|
||||
|
@ -1143,8 +1206,88 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfRecognizedMethod(
|
|||
Fragment body(instruction_cursor);
|
||||
body += CheckStackOverflowInPrologue(function.token_pos());
|
||||
|
||||
if (function.IsDynamicInvocationForwarder()) {
|
||||
body += BuildDefaultTypeHandling(function);
|
||||
BuildTypeArgumentTypeChecks(
|
||||
TypeChecksToBuild::kCheckNonCovariantTypeParameterBounds, &body);
|
||||
BuildArgumentTypeChecks(&body, &body, nullptr);
|
||||
}
|
||||
|
||||
const MethodRecognizer::Kind kind = function.recognized_kind();
|
||||
switch (kind) {
|
||||
case MethodRecognizer::kObjectArrayGetIndexed:
|
||||
case MethodRecognizer::kGrowableArrayGetIndexed:
|
||||
case MethodRecognizer::kInt8ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt8ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint8ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint8ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint8ClampedArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
|
||||
case MethodRecognizer::kInt16ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt16ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint16ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint16ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt32ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint32ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt64ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint64ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat32ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat64ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat64x2ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat64x2ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt32x4ArrayGetIndexed: {
|
||||
ASSERT_EQUAL(function.NumParameters(), 2);
|
||||
intptr_t array_cid = MethodRecognizer::MethodKindToReceiverCid(kind);
|
||||
const Representation elem_rep =
|
||||
RepresentationUtils::RepresentationOfArrayElement(array_cid);
|
||||
body += LoadLocal(parsed_function_->RawParameterVariable(0));
|
||||
body += LoadNativeField(Slot::GetLengthFieldForArrayCid(array_cid));
|
||||
body += LoadLocal(parsed_function_->RawParameterVariable(1));
|
||||
body += GenericCheckBound();
|
||||
LocalVariable* safe_index = MakeTemporary();
|
||||
body += LoadLocal(parsed_function_->RawParameterVariable(0));
|
||||
if (IsTypedDataBaseClassId(array_cid) && !CanUnboxElements(array_cid)) {
|
||||
const auto& native_function =
|
||||
TypedListGetNativeFunction(thread_, array_cid);
|
||||
body += LoadLocal(safe_index);
|
||||
body += UnboxTruncate(kUnboxedIntPtr);
|
||||
body += IntConstant(Utils::ShiftForPowerOfTwo(
|
||||
RepresentationUtils::ValueSize(elem_rep)));
|
||||
body += BinaryIntegerOp(Token::kSHL, kUnboxedIntPtr,
|
||||
/*is_truncating=*/true);
|
||||
body += StaticCall(TokenPosition::kNoSource, native_function, 2,
|
||||
ICData::kNoRebind);
|
||||
} else {
|
||||
if (kind == MethodRecognizer::kGrowableArrayGetIndexed) {
|
||||
body += LoadNativeField(Slot::GrowableObjectArray_data());
|
||||
array_cid = kArrayCid;
|
||||
} else if (IsExternalTypedDataClassId(array_cid)) {
|
||||
body += LoadNativeField(Slot::PointerBase_data(),
|
||||
InnerPointerAccess::kCannotBeInnerPointer);
|
||||
}
|
||||
body += LoadLocal(safe_index);
|
||||
body +=
|
||||
LoadIndexed(array_cid,
|
||||
/*index_scale=*/
|
||||
compiler::target::Instance::ElementSizeFor(array_cid),
|
||||
/*index_unboxed=*/
|
||||
GenericCheckBoundInstr::UseUnboxedRepresentation());
|
||||
if (elem_rep == kUnboxedFloat) {
|
||||
body += FloatToDouble();
|
||||
}
|
||||
}
|
||||
body += DropTempsPreserveTop(1); // Drop [safe_index], keep result.
|
||||
break;
|
||||
}
|
||||
case MethodRecognizer::kRecord_fieldAt:
|
||||
ASSERT_EQUAL(function.NumParameters(), 2);
|
||||
body += LoadLocal(parsed_function_->RawParameterVariable(0));
|
||||
|
@ -1959,40 +2102,6 @@ Fragment FlowGraphBuilder::BuildTypedDataViewFactoryConstructor(
|
|||
return body;
|
||||
}
|
||||
|
||||
static bool CanUnboxElements(classid_t cid) {
|
||||
switch (RepresentationUtils::RepresentationOfArrayElement(cid)) {
|
||||
case kUnboxedFloat:
|
||||
case kUnboxedDouble:
|
||||
return FlowGraphCompiler::SupportsUnboxedDoubles();
|
||||
case kUnboxedInt32x4:
|
||||
case kUnboxedFloat32x4:
|
||||
case kUnboxedFloat64x2:
|
||||
return FlowGraphCompiler::SupportsUnboxedSimd128();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static const Function& TypedListGetNativeFunction(Thread* thread,
|
||||
classid_t cid) {
|
||||
auto& state = thread->compiler_state();
|
||||
switch (RepresentationUtils::RepresentationOfArrayElement(cid)) {
|
||||
case kUnboxedFloat:
|
||||
return state.TypedListGetFloat32();
|
||||
case kUnboxedDouble:
|
||||
return state.TypedListGetFloat64();
|
||||
case kUnboxedInt32x4:
|
||||
return state.TypedListGetInt32x4();
|
||||
case kUnboxedFloat32x4:
|
||||
return state.TypedListGetFloat32x4();
|
||||
case kUnboxedFloat64x2:
|
||||
return state.TypedListGetFloat64x2();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return Object::null_function();
|
||||
}
|
||||
}
|
||||
|
||||
Fragment FlowGraphBuilder::BuildTypedListGet(const Function& function,
|
||||
classid_t cid) {
|
||||
const intptr_t kNumParameters = 2;
|
||||
|
@ -4380,6 +4489,9 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfDynamicInvocationForwarder(
|
|||
if (target.IsMethodExtractor()) {
|
||||
return BuildGraphOfMethodExtractor(target);
|
||||
}
|
||||
if (FlowGraphBuilder::IsRecognizedMethodForFlowGraph(function)) {
|
||||
return BuildGraphOfRecognizedMethod(function);
|
||||
}
|
||||
|
||||
graph_entry_ = new (Z) GraphEntryInstr(*parsed_function_, osr_id_);
|
||||
|
||||
|
|
|
@ -361,6 +361,12 @@ ScopeBuildingResult* ScopeBuilder::BuildScopes() {
|
|||
const auto& target = Function::ZoneHandle(Z, function.ForwardingTarget());
|
||||
ASSERT(!target.IsNull());
|
||||
|
||||
if (FlowGraphBuilder::IsRecognizedMethodForFlowGraph(function) &&
|
||||
FlowGraphBuilder::IsExpressionTempVarUsedInRecognizedMethodFlowGraph(
|
||||
function)) {
|
||||
needs_expr_temp_ = true;
|
||||
}
|
||||
|
||||
if (helper_.PeekTag() == kField) {
|
||||
// Create [this] variable.
|
||||
const Class& klass = Class::Handle(Z, function.Owner());
|
||||
|
|
|
@ -215,55 +215,6 @@ static Definition* CreateUnboxedResultIfNeeded(BlockBuilder* builder,
|
|||
}
|
||||
}
|
||||
|
||||
static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
|
||||
intptr_t array_cid) {
|
||||
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
||||
auto normal_entry = graph_entry->normal_entry();
|
||||
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
|
||||
|
||||
Definition* array = builder.AddParameter(0);
|
||||
Definition* index = builder.AddParameter(1);
|
||||
|
||||
VerifyParameterIsBoxed(&builder, 0);
|
||||
|
||||
index = CreateBoxedParameterIfNeeded(&builder, index, kUnboxedInt64, 1);
|
||||
index = PrepareIndexedOp(flow_graph, &builder, array, index,
|
||||
Slot::GetLengthFieldForArrayCid(array_cid));
|
||||
|
||||
if (IsExternalTypedDataClassId(array_cid)) {
|
||||
array = builder.AddDefinition(new LoadFieldInstr(
|
||||
new Value(array), Slot::PointerBase_data(),
|
||||
InnerPointerAccess::kCannotBeInnerPointer, builder.Source()));
|
||||
}
|
||||
|
||||
Definition* result = builder.AddDefinition(new LoadIndexedInstr(
|
||||
new Value(array), new Value(index), /*index_unboxed=*/false,
|
||||
/*index_scale=*/target::Instance::ElementSizeFor(array_cid), array_cid,
|
||||
kAlignedAccess, DeoptId::kNone, builder.Source()));
|
||||
|
||||
// We don't perform [RangeAnalysis] for graph intrinsics. To inform the
|
||||
// following boxing instruction about a more precise range we attach it here
|
||||
// manually.
|
||||
// http://dartbug.com/36632
|
||||
auto const rep = RepresentationUtils::RepresentationOfArrayElement(array_cid);
|
||||
if (RepresentationUtils::IsUnboxedInteger(rep)) {
|
||||
result->set_range(Range::Full(rep));
|
||||
}
|
||||
const bool clear_environment =
|
||||
RangeUtils::Fits(result->range(), RangeBoundary::kRangeBoundarySmi);
|
||||
|
||||
// Box and/or convert result if necessary.
|
||||
if (RepresentationUtils::IsUnboxed(rep)) {
|
||||
result = CreateBoxedResultIfNeeded(&builder, result, rep);
|
||||
}
|
||||
if (result->IsBoxInteger() && clear_environment) {
|
||||
result->AsBoxInteger()->ClearEnv();
|
||||
}
|
||||
result = CreateUnboxedResultIfNeeded(&builder, result);
|
||||
builder.AddReturn(new Value(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
|
||||
intptr_t array_cid) {
|
||||
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
||||
|
@ -326,14 +277,6 @@ static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
|
|||
return true;
|
||||
}
|
||||
|
||||
#define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
|
||||
bool GraphIntrinsifier::Build_##enum_name##GetIndexed( \
|
||||
FlowGraph* flow_graph) { \
|
||||
return IntrinsifyArrayGetIndexed( \
|
||||
flow_graph, MethodRecognizer::MethodKindToReceiverCid( \
|
||||
MethodRecognizer::k##enum_name##GetIndexed)); \
|
||||
}
|
||||
|
||||
#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name) \
|
||||
bool GraphIntrinsifier::Build_##enum_name##SetIndexed( \
|
||||
FlowGraph* flow_graph) { \
|
||||
|
@ -342,39 +285,20 @@ static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
|
|||
MethodRecognizer::k##enum_name##SetIndexed)); \
|
||||
}
|
||||
|
||||
DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Int8Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Uint8Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(ExternalUint8Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Uint8ClampedArray)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(ExternalUint8ClampedArray)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Int16Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Uint16Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Int32Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Uint32Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Int64Array)
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(Uint64Array)
|
||||
|
||||
#define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
|
||||
DEFINE_ARRAY_GETTER_INTRINSIC(enum_name) \
|
||||
DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
|
||||
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int64Array)
|
||||
DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint64Array)
|
||||
|
||||
#undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
|
||||
#undef DEFINE_ARRAY_GETTER_INTRINSIC
|
||||
#undef DEFINE_ARRAY_SETTER_INTRINSIC
|
||||
|
||||
#define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
|
||||
bool GraphIntrinsifier::Build_##enum_name##GetIndexed( \
|
||||
FlowGraph* flow_graph) { \
|
||||
if (!FlowGraphCompiler::SupportsUnboxedDoubles()) { \
|
||||
return false; \
|
||||
} \
|
||||
return IntrinsifyArrayGetIndexed( \
|
||||
flow_graph, MethodRecognizer::MethodKindToReceiverCid( \
|
||||
MethodRecognizer::k##enum_name##GetIndexed)); \
|
||||
}
|
||||
|
||||
#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name) \
|
||||
bool GraphIntrinsifier::Build_##enum_name##SetIndexed( \
|
||||
FlowGraph* flow_graph) { \
|
||||
|
@ -386,28 +310,11 @@ DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint64Array)
|
|||
MethodRecognizer::k##enum_name##SetIndexed)); \
|
||||
}
|
||||
|
||||
#define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
|
||||
DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name) \
|
||||
DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
|
||||
DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(Float64Array)
|
||||
DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(Float32Array)
|
||||
|
||||
DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
|
||||
DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
|
||||
|
||||
#undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
|
||||
#undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
|
||||
#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
|
||||
|
||||
#define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \
|
||||
bool GraphIntrinsifier::Build_##enum_name##GetIndexed( \
|
||||
FlowGraph* flow_graph) { \
|
||||
if (!FlowGraphCompiler::SupportsUnboxedSimd128()) { \
|
||||
return false; \
|
||||
} \
|
||||
return IntrinsifyArrayGetIndexed( \
|
||||
flow_graph, MethodRecognizer::MethodKindToReceiverCid( \
|
||||
MethodRecognizer::k##enum_name##GetIndexed)); \
|
||||
}
|
||||
|
||||
#define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name) \
|
||||
bool GraphIntrinsifier::Build_##enum_name##SetIndexed( \
|
||||
FlowGraph* flow_graph) { \
|
||||
|
@ -419,16 +326,10 @@ DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
|
|||
MethodRecognizer::k##enum_name##SetIndexed)); \
|
||||
}
|
||||
|
||||
#define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name) \
|
||||
DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name) \
|
||||
DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name)
|
||||
DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(Float32x4Array)
|
||||
DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(Int32x4Array)
|
||||
DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(Float64x2Array)
|
||||
|
||||
DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array)
|
||||
DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array)
|
||||
DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array)
|
||||
|
||||
#undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS
|
||||
#undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC
|
||||
#undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC
|
||||
|
||||
static bool BuildSimdOp(FlowGraph* flow_graph, intptr_t cid, Token::Kind kind) {
|
||||
|
@ -596,32 +497,6 @@ bool GraphIntrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GraphIntrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) {
|
||||
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
||||
auto normal_entry = graph_entry->normal_entry();
|
||||
BlockBuilder builder(flow_graph, normal_entry, /*with_frame=*/false);
|
||||
|
||||
Definition* growable_array = builder.AddParameter(0);
|
||||
Definition* index = builder.AddParameter(1);
|
||||
|
||||
VerifyParameterIsBoxed(&builder, 0);
|
||||
|
||||
index = CreateBoxedParameterIfNeeded(&builder, index, kUnboxedInt64, 1);
|
||||
index = PrepareIndexedOp(flow_graph, &builder, growable_array, index,
|
||||
Slot::GrowableObjectArray_length());
|
||||
|
||||
Definition* backing_store = builder.AddDefinition(
|
||||
new LoadFieldInstr(new Value(growable_array),
|
||||
Slot::GrowableObjectArray_data(), builder.Source()));
|
||||
Definition* result = builder.AddDefinition(new LoadIndexedInstr(
|
||||
new Value(backing_store), new Value(index), /*index_unboxed=*/false,
|
||||
/*index_scale=*/target::Instance::ElementSizeFor(kArrayCid), kArrayCid,
|
||||
kAlignedAccess, DeoptId::kNone, builder.Source()));
|
||||
result = CreateUnboxedResultIfNeeded(&builder, result);
|
||||
builder.AddReturn(new Value(result));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GraphIntrinsifier::Build_ObjectArraySetIndexedUnchecked(
|
||||
FlowGraph* flow_graph) {
|
||||
GraphEntryInstr* graph_entry = flow_graph->graph_entry();
|
||||
|
|
|
@ -108,14 +108,23 @@ intptr_t MethodRecognizer::MethodKindToReceiverCid(Kind kind) {
|
|||
case kFloat32ArraySetIndexed:
|
||||
return kTypedDataFloat32ArrayCid;
|
||||
|
||||
case kExternalFloat32ArrayGetIndexed:
|
||||
return kExternalTypedDataFloat32ArrayCid;
|
||||
|
||||
case kFloat64ArrayGetIndexed:
|
||||
case kFloat64ArraySetIndexed:
|
||||
return kTypedDataFloat64ArrayCid;
|
||||
|
||||
case kExternalFloat64ArrayGetIndexed:
|
||||
return kExternalTypedDataFloat64ArrayCid;
|
||||
|
||||
case kInt8ArrayGetIndexed:
|
||||
case kInt8ArraySetIndexed:
|
||||
return kTypedDataInt8ArrayCid;
|
||||
|
||||
case kExternalInt8ArrayGetIndexed:
|
||||
return kExternalTypedDataInt8ArrayCid;
|
||||
|
||||
case kUint8ArrayGetIndexed:
|
||||
case kUint8ArraySetIndexed:
|
||||
return kTypedDataUint8ArrayCid;
|
||||
|
@ -136,38 +145,65 @@ intptr_t MethodRecognizer::MethodKindToReceiverCid(Kind kind) {
|
|||
case kInt16ArraySetIndexed:
|
||||
return kTypedDataInt16ArrayCid;
|
||||
|
||||
case kExternalInt16ArrayGetIndexed:
|
||||
return kExternalTypedDataInt16ArrayCid;
|
||||
|
||||
case kUint16ArrayGetIndexed:
|
||||
case kUint16ArraySetIndexed:
|
||||
return kTypedDataUint16ArrayCid;
|
||||
|
||||
case kExternalUint16ArrayGetIndexed:
|
||||
return kExternalTypedDataUint16ArrayCid;
|
||||
|
||||
case kInt32ArrayGetIndexed:
|
||||
case kInt32ArraySetIndexed:
|
||||
return kTypedDataInt32ArrayCid;
|
||||
|
||||
case kExternalInt32ArrayGetIndexed:
|
||||
return kExternalTypedDataInt32ArrayCid;
|
||||
|
||||
case kUint32ArrayGetIndexed:
|
||||
case kUint32ArraySetIndexed:
|
||||
return kTypedDataUint32ArrayCid;
|
||||
|
||||
case kExternalUint32ArrayGetIndexed:
|
||||
return kExternalTypedDataUint32ArrayCid;
|
||||
|
||||
case kInt64ArrayGetIndexed:
|
||||
case kInt64ArraySetIndexed:
|
||||
return kTypedDataInt64ArrayCid;
|
||||
|
||||
case kExternalInt64ArrayGetIndexed:
|
||||
return kExternalTypedDataInt64ArrayCid;
|
||||
|
||||
case kUint64ArrayGetIndexed:
|
||||
case kUint64ArraySetIndexed:
|
||||
return kTypedDataUint64ArrayCid;
|
||||
|
||||
case kExternalUint64ArrayGetIndexed:
|
||||
return kExternalTypedDataUint64ArrayCid;
|
||||
|
||||
case kFloat32x4ArrayGetIndexed:
|
||||
case kFloat32x4ArraySetIndexed:
|
||||
return kTypedDataFloat32x4ArrayCid;
|
||||
|
||||
case kExternalFloat32x4ArrayGetIndexed:
|
||||
return kExternalTypedDataFloat32x4ArrayCid;
|
||||
|
||||
case kInt32x4ArrayGetIndexed:
|
||||
case kInt32x4ArraySetIndexed:
|
||||
return kTypedDataInt32x4ArrayCid;
|
||||
|
||||
case kExternalInt32x4ArrayGetIndexed:
|
||||
return kExternalTypedDataInt32x4ArrayCid;
|
||||
|
||||
case kFloat64x2ArrayGetIndexed:
|
||||
case kFloat64x2ArraySetIndexed:
|
||||
return kTypedDataFloat64x2ArrayCid;
|
||||
|
||||
case kExternalFloat64x2ArrayGetIndexed:
|
||||
return kExternalTypedDataFloat64x2ArrayCid;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,37 @@ namespace dart {
|
|||
V(::, identical, ObjectIdentical, 0x0407f735) \
|
||||
V(ClassID, getID, ClassIDgetID, 0xdc7cfcaa) \
|
||||
V(Object, Object., ObjectConstructor, 0xab6d6cfa) \
|
||||
V(_Array, [], ObjectArrayGetIndexed, 0x78e66c72) \
|
||||
V(_GrowableList, [], GrowableArrayGetIndexed, 0x78e66c72) \
|
||||
V(_Int8List, [], Int8ArrayGetIndexed, 0x2321c262) \
|
||||
V(_ExternalInt8Array, [], ExternalInt8ArrayGetIndexed, 0x2321c262) \
|
||||
V(_Uint8List, [], Uint8ArrayGetIndexed, 0x2321c262) \
|
||||
V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 0x2321c262) \
|
||||
V(_Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 0x2321c262) \
|
||||
V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed, \
|
||||
0x2321c262) \
|
||||
V(_Int16List, [], Int16ArrayGetIndexed, 0x2321c262) \
|
||||
V(_ExternalInt16Array, [], ExternalInt16ArrayGetIndexed, 0x2321c262) \
|
||||
V(_Uint16List, [], Uint16ArrayGetIndexed, 0x2321c262) \
|
||||
V(_ExternalUint16Array, [], ExternalUint16ArrayGetIndexed, 0x2321c262) \
|
||||
V(_Int32List, [], Int32ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_ExternalInt32Array, [], ExternalInt32ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_Uint32List, [], Uint32ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_ExternalUint32Array, [], ExternalUint32ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_Int64List, [], Int64ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_ExternalInt64Array, [], ExternalInt64ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_Uint64List, [], Uint64ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_ExternalUint64Array, [], ExternalUint64ArrayGetIndexed, 0x2321bea1) \
|
||||
V(_Float32List, [], Float32ArrayGetIndexed, 0x0784da3c) \
|
||||
V(_ExternalFloat32Array, [], ExternalFloat32ArrayGetIndexed, 0x0784da3c) \
|
||||
V(_Float64List, [], Float64ArrayGetIndexed, 0x0784da3c) \
|
||||
V(_ExternalFloat64Array, [], ExternalFloat64ArrayGetIndexed, 0x0784da3c) \
|
||||
V(_Float32x4List, [], Float32x4ArrayGetIndexed, 0xb0f79623) \
|
||||
V(_ExternalFloat32x4Array, [], ExternalFloat32x4ArrayGetIndexed, 0xb0f79623) \
|
||||
V(_Float64x2List, [], Float64x2ArrayGetIndexed, 0x5fd5df39) \
|
||||
V(_ExternalFloat64x2Array, [], ExternalFloat64x2ArrayGetIndexed, 0x5fd5df39) \
|
||||
V(_Int32x4List, [], Int32x4ArrayGetIndexed, 0x4967f00b) \
|
||||
V(_ExternalInt32x4Array, [], ExternalInt32x4ArrayGetIndexed, 0x4967f00b) \
|
||||
V(_List, ., ObjectArrayAllocate, 0x4c8eae02) \
|
||||
V(_List, []=, ObjectArraySetIndexed, 0x3a3252da) \
|
||||
V(_GrowableList, ._withData, GrowableArrayAllocateWithData, 0x19394cc1) \
|
||||
|
@ -394,39 +425,22 @@ namespace dart {
|
|||
V(_IntegerImplementation, <<, Integer_shl, 0x2d253e1b) \
|
||||
|
||||
#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V) \
|
||||
V(_Int8List, [], Int8ArrayGetIndexed, 0x7b31eba4) \
|
||||
V(_Int8List, []=, Int8ArraySetIndexed, 0x02f7bc29) \
|
||||
V(_Uint8List, [], Uint8ArrayGetIndexed, 0xe0aa6f64) \
|
||||
V(_Uint8List, []=, Uint8ArraySetIndexed, 0xc8fdea5d) \
|
||||
V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 0xe0aa6f64) \
|
||||
V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, 0xc8fdea5d) \
|
||||
V(_Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 0xe0aa6f64) \
|
||||
V(_Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 0x45020fa5) \
|
||||
V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed, \
|
||||
0xe0aa6f64) \
|
||||
V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed, \
|
||||
0x45020fa5) \
|
||||
V(_Int16List, [], Int16ArrayGetIndexed, 0x97526723) \
|
||||
V(_Int16List, []=, Int16ArraySetIndexed, 0x3c52d77c) \
|
||||
V(_Uint16List, [], Uint16ArrayGetIndexed, 0x4cba19cf) \
|
||||
V(_Uint16List, []=, Uint16ArraySetIndexed, 0x96e38a7c) \
|
||||
V(_Int32List, [], Int32ArrayGetIndexed, 0x1113e36a) \
|
||||
V(_Int32List, []=, Int32ArraySetIndexed, 0x7cf2875c) \
|
||||
V(_Uint32List, [], Uint32ArrayGetIndexed, 0x97cbdf48) \
|
||||
V(_Uint32List, []=, Uint32ArraySetIndexed, 0xe5065f1c) \
|
||||
V(_Int64List, [], Int64ArrayGetIndexed, 0x03bd8740) \
|
||||
V(_Int64List, []=, Int64ArraySetIndexed, 0x672a7e1c) \
|
||||
V(_Uint64List, [], Uint64ArrayGetIndexed, 0xcc7e9c0c) \
|
||||
V(_Uint64List, []=, Uint64ArraySetIndexed, 0x5e2325bc) \
|
||||
V(_Float64List, [], Float64ArrayGetIndexed, 0x4cf25eb3) \
|
||||
V(_Float64List, []=, Float64ArraySetIndexed, 0x84d73842) \
|
||||
V(_Float32List, [], Float32ArrayGetIndexed, 0x289ee54d) \
|
||||
V(_Float32List, []=, Float32ArraySetIndexed, 0x5e323082) \
|
||||
V(_Float32x4List, [], Float32x4ArrayGetIndexed, 0x874fca98) \
|
||||
V(_Float32x4List, []=, Float32x4ArraySetIndexed, 0xadc022db) \
|
||||
V(_Int32x4List, [], Int32x4ArrayGetIndexed, 0xc9f525b4) \
|
||||
V(_Int32x4List, []=, Int32x4ArraySetIndexed, 0xf38ac7d3) \
|
||||
V(_Float64x2List, [], Float64x2ArrayGetIndexed, 0x7a32de78) \
|
||||
V(_Float64x2List, []=, Float64x2ArraySetIndexed, 0xf316f725) \
|
||||
V(_TypedListBase, get:length, TypedListBaseLength, 0x5842648b) \
|
||||
V(_ByteDataView, get:length, ByteDataViewLength, 0x5842648b) \
|
||||
|
@ -445,13 +459,11 @@ namespace dart {
|
|||
|
||||
#define GRAPH_CORE_INTRINSICS_LIST(V) \
|
||||
V(_Array, get:length, ObjectArrayLength, 0x5842648b) \
|
||||
V(_Array, [], ObjectArrayGetIndexed, 0x78e668b1) \
|
||||
V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, 0xe6212a10) \
|
||||
V(_GrowableList, get:length, GrowableArrayLength, 0x5842648b) \
|
||||
V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x7d911012) \
|
||||
V(_GrowableList, _setData, GrowableArraySetData, 0xbdcbb43b) \
|
||||
V(_GrowableList, _setLength, GrowableArraySetLength, 0xcc0d6dd6) \
|
||||
V(_GrowableList, [], GrowableArrayGetIndexed, 0x78e668b1) \
|
||||
V(_GrowableList, _setIndexed, GrowableArraySetIndexedUnchecked, 0x513c774f) \
|
||||
V(_StringBase, get:length, StringBaseLength, 0x5842648b) \
|
||||
V(_Smi, ~, Smi_bitNegate, 0x82466cfc) \
|
||||
|
|
|
@ -9193,6 +9193,36 @@ bool Function::RecognizedKindForceOptimize() const {
|
|||
// Uses unboxed/untagged data not supported in unoptimized, or uses
|
||||
// LoadIndexed/StoreIndexed/MemoryCopy instructions with typed data
|
||||
// arrays, which requires optimization for payload extraction.
|
||||
case MethodRecognizer::kObjectArrayGetIndexed:
|
||||
case MethodRecognizer::kGrowableArrayGetIndexed:
|
||||
case MethodRecognizer::kInt8ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt8ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint8ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint8ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint8ClampedArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
|
||||
case MethodRecognizer::kInt16ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt16ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint16ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint16ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt32ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint32ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt64ArrayGetIndexed:
|
||||
case MethodRecognizer::kUint64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalUint64ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat32ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat32ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat64ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat64ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kFloat64x2ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalFloat64x2ArrayGetIndexed:
|
||||
case MethodRecognizer::kInt32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kExternalInt32x4ArrayGetIndexed:
|
||||
case MethodRecognizer::kCopyRangeFromUint8ListToOneByteString:
|
||||
case MethodRecognizer::kFinalizerBase_getIsolateFinalizers:
|
||||
case MethodRecognizer::kFinalizerBase_setIsolate:
|
||||
|
|
|
@ -5,8 +5,9 @@
|
|||
part of "core_patch.dart";
|
||||
|
||||
abstract class _Array<E> extends FixedLengthListBase<E> {
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:external-name", "List_getIndexed")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external E operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
|
|
|
@ -259,8 +259,9 @@ class _GrowableList<T> extends ListBase<T> {
|
|||
@pragma("vm:external-name", "GrowableList_setData")
|
||||
external void _setData(_List array);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:external-name", "GrowableList_getIndexed")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external T operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "other")
|
||||
|
|
|
@ -2264,12 +2264,11 @@ final class _Int8List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt8(index);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2320,12 +2319,11 @@ final class _Uint8List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint8(index);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2379,12 +2377,11 @@ final class _Uint8ClampedList extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint8(index);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2441,12 +2438,11 @@ final class _Int16List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt16(index * Int16List.bytesPerElement);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2510,12 +2506,11 @@ final class _Uint16List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint16(index * Uint16List.bytesPerElement);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2579,11 +2574,10 @@ final class _Int32List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt32(index * Int32List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2634,11 +2628,10 @@ final class _Uint32List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint32(index * Uint32List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2689,11 +2682,10 @@ final class _Int64List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt64(index * Int64List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2744,11 +2736,10 @@ final class _Uint64List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint64(index * Uint64List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -2799,12 +2790,11 @@ final class _Float32List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Double")
|
||||
double operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat32(index * Float32List.bytesPerElement);
|
||||
}
|
||||
external double operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, double value) {
|
||||
|
@ -2855,12 +2845,11 @@ final class _Float64List extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Double")
|
||||
double operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat64(index * Float64List.bytesPerElement);
|
||||
}
|
||||
external double operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, double value) {
|
||||
|
@ -2910,12 +2899,11 @@ final class _Float32x4List extends _TypedList
|
|||
throw "Unreachable";
|
||||
}
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", _Float32x4)
|
||||
Float32x4 operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat32x4(index * Float32x4List.bytesPerElement);
|
||||
}
|
||||
external Float32x4 operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, Float32x4 value) {
|
||||
|
@ -2965,12 +2953,11 @@ final class _Int32x4List extends _TypedList
|
|||
throw "Unreachable";
|
||||
}
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", _Int32x4)
|
||||
Int32x4 operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt32x4(index * Int32x4List.bytesPerElement);
|
||||
}
|
||||
external Int32x4 operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, Int32x4 value) {
|
||||
|
@ -3020,12 +3007,11 @@ final class _Float64x2List extends _TypedList
|
|||
throw "Unreachable";
|
||||
}
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", _Float64x2)
|
||||
Float64x2 operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat64x2(index * Float64x2List.bytesPerElement);
|
||||
}
|
||||
external Float64x2 operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, Float64x2 value) {
|
||||
|
@ -3061,10 +3047,11 @@ final class _ExternalInt8Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt8(index);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3099,12 +3086,11 @@ final class _ExternalUint8Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint8(index);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -3143,12 +3129,11 @@ final class _ExternalUint8ClampedArray extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint8(index);
|
||||
}
|
||||
external int operator [](int index);
|
||||
|
||||
@pragma("vm:recognized", "graph-intrinsic")
|
||||
void operator []=(int index, int value) {
|
||||
|
@ -3190,10 +3175,11 @@ final class _ExternalInt16Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt16(index * Int16List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3228,10 +3214,11 @@ final class _ExternalUint16Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint16(index * Uint16List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Smi")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3266,10 +3253,10 @@ final class _ExternalInt32Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt32(index * Int32List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3304,10 +3291,10 @@ final class _ExternalUint32Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint32(index * Uint32List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3342,10 +3329,10 @@ final class _ExternalInt64Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt64(index * Int64List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3380,10 +3367,10 @@ final class _ExternalUint64Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
int operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getUint64(index * Uint64List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
external int operator [](int index);
|
||||
|
||||
void operator []=(int index, int value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3418,10 +3405,11 @@ final class _ExternalFloat32Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
double operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat32(index * Float32List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Double")
|
||||
external double operator [](int index);
|
||||
|
||||
void operator []=(int index, double value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3456,10 +3444,11 @@ final class _ExternalFloat64Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
double operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat64(index * Float64List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", "dart:core#_Double")
|
||||
external double operator [](int index);
|
||||
|
||||
void operator []=(int index, double value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3494,10 +3483,11 @@ final class _ExternalFloat32x4Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
Float32x4 operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat32x4(index * Float32x4List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", _Float32x4)
|
||||
external Float32x4 operator [](int index);
|
||||
|
||||
void operator []=(int index, Float32x4 value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3532,10 +3522,11 @@ final class _ExternalInt32x4Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
Int32x4 operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getInt32x4(index * Int32x4List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", _Int32x4)
|
||||
external Int32x4 operator [](int index);
|
||||
|
||||
void operator []=(int index, Int32x4 value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
@ -3570,10 +3561,11 @@ final class _ExternalFloat64x2Array extends _TypedList
|
|||
}
|
||||
|
||||
// Method(s) implementing the List interface.
|
||||
Float64x2 operator [](int index) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
return _getFloat64x2(index * Float64x2List.bytesPerElement);
|
||||
}
|
||||
@pragma("vm:recognized", "other")
|
||||
@pragma("vm:prefer-inline")
|
||||
@pragma("vm:idempotent")
|
||||
@pragma("vm:exact-result-type", _Float64x2)
|
||||
external Float64x2 operator [](int index);
|
||||
|
||||
void operator []=(int index, Float64x2 value) {
|
||||
index = _typedDataIndexCheck(this, index, length);
|
||||
|
|
Loading…
Reference in a new issue