mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 16:00:45 +00:00
Revert "[vm, interpreter] Invoke field as a bytecode."
This reverts commit c85631330d
.
Reason for revert: precompilation build failure
Original change's description:
> [vm, interpreter] Invoke field as a bytecode.
>
> Simplify invocation.
>
> Change-Id: I2d605d5f2f17e0e98499a19b9d9b6059682100b5
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99884
> Reviewed-by: Régis Crelier <regis@google.com>
> Reviewed-by: Alexander Markov <alexmarkov@google.com>
TBR=rmacnak@google.com,alexmarkov@google.com,regis@google.com
Change-Id: If417cb83e55e392895cdbdd263757f3e877f5ee5
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99961
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
parent
c85631330d
commit
3d1ca4ae39
|
@ -4695,8 +4695,6 @@ void Serializer::AddVMIsolateBaseObjects() {
|
|||
"<method extractor>");
|
||||
AddBaseObject(Object::invoke_closure_bytecode().raw(), "Bytecode",
|
||||
"<invoke closure>");
|
||||
AddBaseObject(Object::invoke_field_bytecode().raw(), "Bytecode",
|
||||
"<invoke field>");
|
||||
|
||||
for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
|
||||
AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i],
|
||||
|
@ -5157,7 +5155,6 @@ void Deserializer::AddVMIsolateBaseObjects() {
|
|||
AddBaseObject(Object::implicit_static_getter_bytecode().raw());
|
||||
AddBaseObject(Object::method_extractor_bytecode().raw());
|
||||
AddBaseObject(Object::invoke_closure_bytecode().raw());
|
||||
AddBaseObject(Object::invoke_field_bytecode().raw());
|
||||
|
||||
for (intptr_t i = 0; i < ArgumentsDescriptor::kCachedDescriptorCount; i++) {
|
||||
AddBaseObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
|
||||
|
|
|
@ -68,11 +68,10 @@ void BytecodeMetadataHelper::ReadMetadata(const Function& function) {
|
|||
function.AttachBytecode(Object::method_extractor_bytecode());
|
||||
return;
|
||||
case RawFunction::kInvokeFieldDispatcher:
|
||||
if (Class::Handle(function.Owner()).id() == kClosureCid) {
|
||||
function.AttachBytecode(Object::invoke_closure_bytecode());
|
||||
} else {
|
||||
function.AttachBytecode(Object::invoke_field_bytecode());
|
||||
if (Class::Handle(function.Owner()).id() != kClosureCid) {
|
||||
break;
|
||||
}
|
||||
function.AttachBytecode(Object::invoke_closure_bytecode());
|
||||
return;
|
||||
default: {
|
||||
}
|
||||
|
|
|
@ -526,7 +526,7 @@ namespace dart {
|
|||
V(CompareDoubleGe, 0, ___, ___, ___) \
|
||||
V(CompareDoubleLe, 0, ___, ___, ___) \
|
||||
|
||||
// These bytecodes are only generated within the VM. Reassigning their
|
||||
// These bytecodes are only generated within the VM. Reassinging their
|
||||
// opcodes is not a breaking change.
|
||||
#define INTERNAL_KERNEL_BYTECODES_LIST(V) \
|
||||
V(VMInternal_ImplicitGetter, 0, ___, ___, ___) \
|
||||
|
@ -534,11 +534,6 @@ namespace dart {
|
|||
V(VMInternal_ImplicitStaticGetter, 0, ___, ___, ___) \
|
||||
V(VMInternal_MethodExtractor, 0, ___, ___, ___) \
|
||||
V(VMInternal_InvokeClosure, 0, ___, ___, ___) \
|
||||
V(VMInternal_InvokeField, 0, ___, ___, ___) \
|
||||
V(VMInternal_ForwardDynamicInvocation, 0, ___, ___, ___) \
|
||||
V(VMInternal_DispatchNoSuchMethod, 0, ___, ___, ___) \
|
||||
V(VMInternal_ImplicitStaticClosure, 0, ___, ___, ___) \
|
||||
V(VMInternal_ImplicitInstanceClosure, 0, ___, ___, ___) \
|
||||
|
||||
#define KERNEL_BYTECODES_LIST(V) \
|
||||
PUBLIC_KERNEL_BYTECODES_LIST(V) \
|
||||
|
|
|
@ -615,14 +615,194 @@ DART_NOINLINE bool Interpreter::InvokeCompiled(Thread* thread,
|
|||
return true;
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE bool Interpreter::InvokeBytecode(Thread* thread,
|
||||
RawFunction* function,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP) {
|
||||
DART_NOINLINE bool Interpreter::ProcessInvocation(bool* invoked,
|
||||
Thread* thread,
|
||||
RawFunction* function,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP) {
|
||||
ASSERT(!Function::HasCode(function) && !Function::HasBytecode(function));
|
||||
ASSERT(function == call_top[0]);
|
||||
RawFunction::Kind kind = Function::kind(function);
|
||||
switch (kind) {
|
||||
case RawFunction::kInvokeFieldDispatcher: {
|
||||
const intptr_t type_args_len =
|
||||
InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
|
||||
const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
|
||||
RawObject* receiver = call_base[receiver_idx];
|
||||
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
|
||||
ASSERT(function == FrameFunction(callee_fp));
|
||||
RawFunction* call_function = Function::null();
|
||||
if (function->ptr()->name_ == Symbols::Call().raw()) {
|
||||
RawObject* owner = function->ptr()->owner_;
|
||||
if (owner->GetClassId() == kPatchClassCid) {
|
||||
owner = PatchClass::RawCast(owner)->ptr()->patched_class_;
|
||||
}
|
||||
if (owner == thread->isolate()->object_store()->closure_class()) {
|
||||
// Closure call.
|
||||
call_function = Closure::RawCast(receiver)->ptr()->function_;
|
||||
}
|
||||
}
|
||||
if (call_function == Function::null()) {
|
||||
// Invoke field getter on receiver.
|
||||
call_top[1] = argdesc_; // Save argdesc_.
|
||||
call_top[2] = 0; // Result of runtime call.
|
||||
call_top[3] = receiver; // Receiver.
|
||||
call_top[4] = function->ptr()->name_; // Field name.
|
||||
Exit(thread, *FP, call_top + 5, *pc);
|
||||
NativeArguments native_args(thread, 2, call_top + 3, call_top + 2);
|
||||
if (!InvokeRuntime(thread, this, DRT_GetFieldForDispatch,
|
||||
native_args)) {
|
||||
return false;
|
||||
}
|
||||
argdesc_ = Array::RawCast(call_top[1]);
|
||||
|
||||
// Replace receiver with field value, keep all other arguments, and
|
||||
// invoke 'call' function, or if not found, invoke noSuchMethod.
|
||||
receiver = call_top[2];
|
||||
call_base[receiver_idx] = receiver;
|
||||
|
||||
// If the field value is a closure, no need to resolve 'call' function.
|
||||
// Otherwise, call runtime to resolve 'call' function.
|
||||
if (InterpreterHelpers::GetClassId(receiver) == kClosureCid) {
|
||||
// Closure call.
|
||||
call_function = Closure::RawCast(receiver)->ptr()->function_;
|
||||
} else {
|
||||
// Resolve and invoke the 'call' function.
|
||||
call_top[3] = argdesc_;
|
||||
call_top[4] = 0; // Result of runtime call.
|
||||
Exit(thread, *FP, call_top + 5, *pc);
|
||||
NativeArguments native_args(thread, 2, call_top + 2, call_top + 4);
|
||||
if (!InvokeRuntime(thread, this, DRT_ResolveCallFunction,
|
||||
native_args)) {
|
||||
return false;
|
||||
}
|
||||
argdesc_ = Array::RawCast(call_top[1]);
|
||||
call_function = Function::RawCast(call_top[4]);
|
||||
if (call_function == Function::null()) {
|
||||
// Function 'call' could not be resolved for argdesc_.
|
||||
// Invoke noSuchMethod.
|
||||
const intptr_t argc =
|
||||
receiver_idx + InterpreterHelpers::ArgDescArgCount(argdesc_);
|
||||
RawObject* null_value = Object::null();
|
||||
call_top[1] = null_value;
|
||||
call_top[2] = call_base[receiver_idx];
|
||||
call_top[3] = argdesc_;
|
||||
call_top[4] = null_value; // Array of arguments (will be filled).
|
||||
|
||||
// Allocate array of arguments.
|
||||
{
|
||||
call_top[5] = Smi::New(argc); // length
|
||||
call_top[6] = null_value; // type
|
||||
Exit(thread, *FP, call_top + 7, *pc);
|
||||
NativeArguments native_args(thread, 2, call_top + 5,
|
||||
call_top + 4);
|
||||
if (!InvokeRuntime(thread, this, DRT_AllocateArray,
|
||||
native_args)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy arguments into the newly allocated array.
|
||||
RawArray* array = static_cast<RawArray*>(call_top[4]);
|
||||
ASSERT(array->GetClassId() == kArrayCid);
|
||||
for (intptr_t i = 0; i < argc; i++) {
|
||||
array->ptr()->data()[i] = call_base[i];
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to resolve 'call' function.
|
||||
call_top[5] = Symbols::Call().raw();
|
||||
|
||||
// Invoke noSuchMethod passing down receiver, argument descriptor,
|
||||
// array of arguments, and target name.
|
||||
{
|
||||
Exit(thread, *FP, call_top + 6, *pc);
|
||||
NativeArguments native_args(thread, 4, call_top + 2,
|
||||
call_top + 1);
|
||||
if (!InvokeRuntime(thread, this, DRT_InvokeNoSuchMethod,
|
||||
native_args)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*SP = call_base;
|
||||
**SP = call_top[1];
|
||||
*invoked = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT(call_function != Function::null());
|
||||
// Patch field dispatcher in callee frame with call function.
|
||||
callee_fp[kKBCFunctionSlotFromFp] = call_function;
|
||||
// Do not compile function if it has code or bytecode.
|
||||
if (Function::HasCode(call_function)) {
|
||||
*invoked = true;
|
||||
return InvokeCompiled(thread, call_function, call_base, call_top, pc,
|
||||
FP, SP);
|
||||
}
|
||||
if (Function::HasBytecode(call_function)) {
|
||||
*invoked = false;
|
||||
return true;
|
||||
}
|
||||
function = call_function;
|
||||
break; // Compile and invoke the function.
|
||||
}
|
||||
case RawFunction::kNoSuchMethodDispatcher:
|
||||
// TODO(regis): Implement. For now, use jitted version.
|
||||
break;
|
||||
case RawFunction::kDynamicInvocationForwarder:
|
||||
// TODO(regis): Implement. For now, use jitted version.
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Compile the function to either generate code or load bytecode.
|
||||
call_top[1] = 0; // Code result.
|
||||
call_top[2] = function;
|
||||
Exit(thread, *FP, call_top + 3, *pc);
|
||||
NativeArguments native_args(thread, 1, call_top + 2, call_top + 1);
|
||||
if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
|
||||
return false;
|
||||
}
|
||||
// Reload objects after the call which may trigger GC.
|
||||
function = Function::RawCast(call_top[2]);
|
||||
if (Function::HasCode(function)) {
|
||||
*invoked = true;
|
||||
return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
|
||||
}
|
||||
ASSERT(Function::HasBytecode(function));
|
||||
// Bytecode was loaded in the above compilation step.
|
||||
// The caller will dispatch to the function's bytecode.
|
||||
*invoked = false;
|
||||
ASSERT(thread->vm_tag() == VMTag::kDartInterpretedTagId);
|
||||
ASSERT(thread->top_exit_frame_info() == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE bool Interpreter::Invoke(Thread* thread,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP) {
|
||||
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
|
||||
|
||||
RawFunction* function = FrameFunction(callee_fp);
|
||||
if (Function::HasCode(function)) {
|
||||
return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
|
||||
}
|
||||
if (!Function::HasBytecode(function)) {
|
||||
bool invoked = false;
|
||||
bool result = ProcessInvocation(&invoked, thread, function, call_base,
|
||||
call_top, pc, FP, SP);
|
||||
if (invoked || !result) {
|
||||
return result;
|
||||
}
|
||||
function = FrameFunction(callee_fp); // Function may have been patched.
|
||||
ASSERT(Function::HasBytecode(function));
|
||||
}
|
||||
#if defined(DEBUG)
|
||||
if (IsTracingExecution()) {
|
||||
THR_Print("%" Pu64 " ", icount_);
|
||||
|
@ -630,8 +810,6 @@ DART_FORCE_INLINE bool Interpreter::InvokeBytecode(Thread* thread,
|
|||
Function::Handle(function).ToFullyQualifiedCString());
|
||||
}
|
||||
#endif
|
||||
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
|
||||
ASSERT(function == FrameFunction(callee_fp));
|
||||
RawBytecode* bytecode = function->ptr()->bytecode_;
|
||||
callee_fp[kKBCPcMarkerSlotFromFp] = bytecode;
|
||||
callee_fp[kKBCSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
|
||||
|
@ -645,38 +823,6 @@ DART_FORCE_INLINE bool Interpreter::InvokeBytecode(Thread* thread,
|
|||
return true;
|
||||
}
|
||||
|
||||
DART_FORCE_INLINE bool Interpreter::Invoke(Thread* thread,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP) {
|
||||
RawObject** callee_fp = call_top + kKBCDartFrameFixedSize;
|
||||
RawFunction* function = FrameFunction(callee_fp);
|
||||
|
||||
for (;;) {
|
||||
if (Function::HasCode(function)) {
|
||||
return InvokeCompiled(thread, function, call_base, call_top, pc, FP, SP);
|
||||
}
|
||||
if (Function::HasBytecode(function)) {
|
||||
return InvokeBytecode(thread, function, call_base, call_top, pc, FP, SP);
|
||||
}
|
||||
|
||||
// Compile the function to either generate code or load bytecode.
|
||||
call_top[1] = 0; // Code result.
|
||||
call_top[2] = function;
|
||||
Exit(thread, *FP, call_top + 3, *pc);
|
||||
NativeArguments native_args(thread, 1, call_top + 2, call_top + 1);
|
||||
if (!InvokeRuntime(thread, this, DRT_CompileFunction, native_args)) {
|
||||
return false;
|
||||
}
|
||||
// Reload objects after the call which may trigger GC.
|
||||
function = Function::RawCast(call_top[2]);
|
||||
|
||||
ASSERT(Function::HasCode(function) || Function::HasBytecode(function));
|
||||
}
|
||||
}
|
||||
|
||||
void Interpreter::InlineCacheMiss(int checked_args,
|
||||
Thread* thread,
|
||||
RawICData* icdata,
|
||||
|
@ -3227,9 +3373,6 @@ SwitchDispatch:
|
|||
{
|
||||
BYTECODE(VMInternal_InvokeClosure, 0);
|
||||
|
||||
ASSERT(Function::kind(FrameFunction(FP)) ==
|
||||
RawFunction::kInvokeFieldDispatcher);
|
||||
|
||||
const intptr_t type_args_len =
|
||||
InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
|
||||
const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
|
||||
|
@ -3240,185 +3383,14 @@ SwitchDispatch:
|
|||
Closure::RawCast(FrameArguments(FP, argc)[receiver_idx]);
|
||||
RawFunction* function = receiver->ptr()->function_;
|
||||
|
||||
SP[1] = function;
|
||||
goto TailCallSP1;
|
||||
}
|
||||
if (LIKELY(Function::HasBytecode(function))) {
|
||||
goto TailCallBytecode;
|
||||
}
|
||||
if (LIKELY(Function::HasCode(function))) {
|
||||
goto CallMachineCode;
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(VMInternal_InvokeField, 0);
|
||||
|
||||
RawFunction* function = FrameFunction(FP);
|
||||
ASSERT(Function::kind(function) == RawFunction::kInvokeFieldDispatcher);
|
||||
|
||||
const intptr_t type_args_len =
|
||||
InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
|
||||
const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
|
||||
const intptr_t argc =
|
||||
InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
|
||||
|
||||
RawObject* receiver = FrameArguments(FP, argc)[receiver_idx];
|
||||
|
||||
// Invoke field getter on receiver.
|
||||
{
|
||||
SP[1] = argdesc_; // Save argdesc_.
|
||||
SP[2] = 0; // Result of runtime call.
|
||||
SP[3] = receiver; // Receiver.
|
||||
SP[4] = function->ptr()->name_; // Field name.
|
||||
Exit(thread, FP, SP + 5, pc);
|
||||
NativeArguments native_args(thread, 2, SP + 3, SP + 2);
|
||||
if (!InvokeRuntime(thread, this, DRT_GetFieldForDispatch, native_args)) {
|
||||
HANDLE_EXCEPTION;
|
||||
}
|
||||
argdesc_ = Array::RawCast(SP[1]);
|
||||
}
|
||||
|
||||
// Replace receiver with field value, keep all other arguments, and
|
||||
// invoke 'call' function, or if not found, invoke noSuchMethod.
|
||||
FrameArguments(FP, argc)[receiver_idx] = receiver = SP[2];
|
||||
|
||||
// If the field value is a closure, no need to resolve 'call' function.
|
||||
if (InterpreterHelpers::GetClassId(receiver) == kClosureCid) {
|
||||
SP[1] = Closure::RawCast(receiver)->ptr()->function_;
|
||||
goto TailCallSP1;
|
||||
}
|
||||
|
||||
// Otherwise, call runtime to resolve 'call' function.
|
||||
{
|
||||
SP[1] = 0; // Result slot.
|
||||
SP[2] = receiver;
|
||||
SP[3] = argdesc_;
|
||||
Exit(thread, FP, SP + 4, pc);
|
||||
NativeArguments native_args(thread, 2, SP + 2, SP + 1);
|
||||
if (!InvokeRuntime(thread, this, DRT_ResolveCallFunction, native_args)) {
|
||||
HANDLE_EXCEPTION;
|
||||
}
|
||||
argdesc_ = Array::RawCast(SP[3]);
|
||||
function = Function::RawCast(SP[1]);
|
||||
receiver = SP[2];
|
||||
}
|
||||
|
||||
if (function != Function::null()) {
|
||||
SP[1] = function;
|
||||
goto TailCallSP1;
|
||||
}
|
||||
|
||||
// Function 'call' could not be resolved for argdesc_.
|
||||
// Invoke noSuchMethod.
|
||||
RawObject* null_value = Object::null();
|
||||
SP[1] = null_value;
|
||||
SP[2] = receiver;
|
||||
SP[3] = argdesc_;
|
||||
SP[4] = null_value; // Array of arguments (will be filled).
|
||||
|
||||
// Allocate array of arguments.
|
||||
{
|
||||
SP[5] = Smi::New(argc); // length
|
||||
SP[6] = null_value; // type
|
||||
Exit(thread, FP, SP + 7, pc);
|
||||
NativeArguments native_args(thread, 2, SP + 5, SP + 4);
|
||||
if (!InvokeRuntime(thread, this, DRT_AllocateArray, native_args)) {
|
||||
HANDLE_EXCEPTION;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy arguments into the newly allocated array.
|
||||
RawObject** argv = FrameArguments(FP, argc);
|
||||
RawArray* array = static_cast<RawArray*>(SP[4]);
|
||||
ASSERT(array->GetClassId() == kArrayCid);
|
||||
for (intptr_t i = 0; i < argc; i++) {
|
||||
array->ptr()->data()[i] = argv[i];
|
||||
}
|
||||
|
||||
// We failed to resolve 'call' function.
|
||||
SP[5] = Symbols::Call().raw();
|
||||
|
||||
// Invoke noSuchMethod passing down receiver, argument descriptor,
|
||||
// array of arguments, and target name.
|
||||
{
|
||||
Exit(thread, FP, SP + 6, pc);
|
||||
NativeArguments native_args(thread, 4, SP + 2, SP + 1);
|
||||
if (!InvokeRuntime(thread, this, DRT_InvokeNoSuchMethod, native_args)) {
|
||||
HANDLE_EXCEPTION;
|
||||
}
|
||||
|
||||
++SP; // Result at SP[0]
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(VMInternal_ForwardDynamicInvocation, 0);
|
||||
RawFunction* function = FrameFunction(FP);
|
||||
ASSERT(Function::kind(function) ==
|
||||
RawFunction::kDynamicInvocationForwarder);
|
||||
UNIMPLEMENTED();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(VMInternal_DispatchNoSuchMethod, 0);
|
||||
RawFunction* function = FrameFunction(FP);
|
||||
ASSERT(Function::kind(function) == RawFunction::kNoSuchMethodDispatcher);
|
||||
UNIMPLEMENTED();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(VMInternal_ImplicitStaticClosure, 0);
|
||||
RawFunction* function = FrameFunction(FP);
|
||||
ASSERT(Function::kind(function) == RawFunction::kImplicitClosureFunction);
|
||||
UNIMPLEMENTED();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
BYTECODE(VMInternal_ImplicitInstanceClosure, 0);
|
||||
RawFunction* function = FrameFunction(FP);
|
||||
ASSERT(Function::kind(function) == RawFunction::kImplicitClosureFunction);
|
||||
UNIMPLEMENTED();
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
TailCallSP1:
|
||||
RawFunction* function = Function::RawCast(SP[1]);
|
||||
|
||||
for (;;) {
|
||||
if (Function::HasBytecode(function)) {
|
||||
ASSERT(function->IsFunction());
|
||||
RawBytecode* bytecode = function->ptr()->bytecode_;
|
||||
ASSERT(bytecode->IsBytecode());
|
||||
FP[kKBCFunctionSlotFromFp] = function;
|
||||
FP[kKBCPcMarkerSlotFromFp] = bytecode;
|
||||
pp_ = bytecode->ptr()->object_pool_;
|
||||
pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_);
|
||||
NOT_IN_PRODUCT(pc_ = pc); // For the profiler.
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
if (Function::HasCode(function)) {
|
||||
const intptr_t type_args_len =
|
||||
InterpreterHelpers::ArgDescTypeArgsLen(argdesc_);
|
||||
const intptr_t receiver_idx = type_args_len > 0 ? 1 : 0;
|
||||
const intptr_t argc =
|
||||
InterpreterHelpers::ArgDescArgCount(argdesc_) + receiver_idx;
|
||||
RawObject** argv = FrameArguments(FP, argc);
|
||||
for (intptr_t i = 0; i < argc; i++) {
|
||||
*++SP = argv[i];
|
||||
}
|
||||
|
||||
RawObject** call_base = SP - argc + 1;
|
||||
RawObject** call_top = SP + 1;
|
||||
call_top[0] = function;
|
||||
if (!InvokeCompiled(thread, function, call_base, call_top, &pc, &FP,
|
||||
&SP)) {
|
||||
HANDLE_EXCEPTION;
|
||||
} else {
|
||||
HANDLE_RETURN;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
// Compile the function to either generate code or load bytecode.
|
||||
SP[1] = argdesc_;
|
||||
SP[2] = 0; // Code result.
|
||||
|
@ -3431,8 +3403,47 @@ SwitchDispatch:
|
|||
}
|
||||
function = Function::RawCast(SP[3]);
|
||||
argdesc_ = Array::RawCast(SP[1]);
|
||||
}
|
||||
|
||||
ASSERT(Function::HasCode(function) || Function::HasBytecode(function));
|
||||
if (LIKELY(Function::HasBytecode(function))) {
|
||||
goto TailCallBytecode;
|
||||
}
|
||||
if (LIKELY(Function::HasCode(function))) {
|
||||
goto CallMachineCode;
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
|
||||
{
|
||||
TailCallBytecode:
|
||||
ASSERT(function->IsFunction());
|
||||
RawBytecode* bytecode = function->ptr()->bytecode_;
|
||||
ASSERT(bytecode->IsBytecode());
|
||||
FP[kKBCFunctionSlotFromFp] = function;
|
||||
FP[kKBCPcMarkerSlotFromFp] = bytecode;
|
||||
pp_ = bytecode->ptr()->object_pool_;
|
||||
pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_);
|
||||
NOT_IN_PRODUCT(pc_ = pc); // For the profiler.
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
{
|
||||
CallMachineCode:
|
||||
RawObject** argv = FrameArguments(FP, argc);
|
||||
for (intptr_t i = 0; i < argc; i++) {
|
||||
*++SP = argv[i];
|
||||
}
|
||||
|
||||
RawObject** call_base = SP - argc + 1;
|
||||
RawObject** call_top = SP + 1;
|
||||
call_top[0] = function;
|
||||
if (!InvokeCompiled(thread, function, call_base, call_top, &pc, &FP,
|
||||
&SP)) {
|
||||
HANDLE_EXCEPTION;
|
||||
} else {
|
||||
HANDLE_RETURN;
|
||||
}
|
||||
DISPATCH();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -153,15 +153,16 @@ class Interpreter {
|
|||
RawObject*** FP,
|
||||
RawObject*** SP);
|
||||
|
||||
bool InvokeCompiled(Thread* thread,
|
||||
RawFunction* function,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP);
|
||||
bool ProcessInvocation(bool* invoked,
|
||||
Thread* thread,
|
||||
RawFunction* function,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
uint32_t** pc,
|
||||
RawObject*** FP,
|
||||
RawObject*** SP);
|
||||
|
||||
bool InvokeBytecode(Thread* thread,
|
||||
bool InvokeCompiled(Thread* thread,
|
||||
RawFunction* function,
|
||||
RawObject** call_base,
|
||||
RawObject** call_top,
|
||||
|
|
|
@ -936,17 +936,6 @@ void Object::Init(Isolate* isolate) {
|
|||
invoke_closure_bytecode_->set_exception_handlers(
|
||||
Object::empty_exception_handlers());
|
||||
|
||||
static const KBCInstr invoke_field_instr[2] = {
|
||||
KernelBytecode::Encode(KernelBytecode::kVMInternal_InvokeField),
|
||||
KernelBytecode::Encode(KernelBytecode::kReturnTOS),
|
||||
};
|
||||
*invoke_field_bytecode_ = Bytecode::New(
|
||||
reinterpret_cast<uword>(invoke_field_instr), sizeof(invoke_field_instr),
|
||||
-1, Object::empty_object_pool());
|
||||
invoke_field_bytecode_->set_pc_descriptors(Object::empty_descriptors());
|
||||
invoke_field_bytecode_->set_exception_handlers(
|
||||
Object::empty_exception_handlers());
|
||||
|
||||
// Some thread fields need to be reinitialized as null constants have not been
|
||||
// initialized until now.
|
||||
Thread* thr = Thread::Current();
|
||||
|
@ -1014,8 +1003,6 @@ void Object::Init(Isolate* isolate) {
|
|||
ASSERT(method_extractor_bytecode_->IsBytecode());
|
||||
ASSERT(!invoke_closure_bytecode_->IsSmi());
|
||||
ASSERT(invoke_closure_bytecode_->IsBytecode());
|
||||
ASSERT(!invoke_field_bytecode_->IsSmi());
|
||||
ASSERT(invoke_field_bytecode_->IsBytecode());
|
||||
}
|
||||
|
||||
void Object::FinishInit(Isolate* isolate) {
|
||||
|
@ -5738,6 +5725,8 @@ bool Function::IsBytecodeAllowed(Zone* zone) const {
|
|||
case RawFunction::kIrregexpFunction:
|
||||
case RawFunction::kFfiTrampoline:
|
||||
return false;
|
||||
case RawFunction::kInvokeFieldDispatcher:
|
||||
return Class::Handle(zone, Owner()).id() == kClosureCid;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
@ -5761,6 +5750,14 @@ void Function::AttachBytecode(const Bytecode& value) const {
|
|||
SetInstructions(StubCode::InterpretCall());
|
||||
}
|
||||
}
|
||||
|
||||
bool Function::HasBytecode() const {
|
||||
return raw_ptr()->bytecode_ != Bytecode::null();
|
||||
}
|
||||
|
||||
bool Function::HasBytecode(RawFunction* function) {
|
||||
return function->ptr()->bytecode_ != Bytecode::null();
|
||||
}
|
||||
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
bool Function::HasCode(RawFunction* function) {
|
||||
|
@ -15187,8 +15184,6 @@ static const char* BytecodeStubName(const Bytecode& bytecode) {
|
|||
return "[Bytecode Stub] VMInternal_MethodExtractor";
|
||||
} else if (bytecode.raw() == Object::invoke_closure_bytecode().raw()) {
|
||||
return "[Bytecode Stub] VMInternal_InvokeClosure";
|
||||
} else if (bytecode.raw() == Object::invoke_field_bytecode().raw()) {
|
||||
return "[Bytecode Stub] VMInternal_InvokeField";
|
||||
}
|
||||
return "[unknown stub]";
|
||||
}
|
||||
|
|
|
@ -401,7 +401,6 @@ class Object {
|
|||
V(Bytecode, implicit_static_getter_bytecode) \
|
||||
V(Bytecode, method_extractor_bytecode) \
|
||||
V(Bytecode, invoke_closure_bytecode) \
|
||||
V(Bytecode, invoke_field_bytecode) \
|
||||
V(Instance, sentinel) \
|
||||
V(Instance, transition_sentinel) \
|
||||
V(Instance, unknown_constant) \
|
||||
|
@ -2151,7 +2150,7 @@ class Function : public Object {
|
|||
bool HasCode() const;
|
||||
static bool HasCode(RawFunction* function);
|
||||
#if !defined(DART_PRECOMPILED_RUNTIME)
|
||||
static inline bool HasBytecode(RawFunction* function);
|
||||
static bool HasBytecode(RawFunction* function);
|
||||
#endif
|
||||
|
||||
static intptr_t code_offset() { return OFFSET_OF(RawFunction, code_); }
|
||||
|
@ -2172,7 +2171,7 @@ class Function : public Object {
|
|||
bool IsBytecodeAllowed(Zone* zone) const;
|
||||
void AttachBytecode(const Bytecode& bytecode) const;
|
||||
RawBytecode* bytecode() const { return raw_ptr()->bytecode_; }
|
||||
inline bool HasBytecode() const;
|
||||
bool HasBytecode() const;
|
||||
#endif
|
||||
|
||||
virtual intptr_t Hash() const;
|
||||
|
@ -9384,14 +9383,6 @@ DART_FORCE_INLINE void Object::SetRaw(RawObject* value) {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool Function::HasBytecode() const {
|
||||
return raw_ptr()->bytecode_ != Bytecode::null();
|
||||
}
|
||||
|
||||
bool Function::HasBytecode(RawFunction* function) {
|
||||
return function->ptr()->bytecode_ != Bytecode::null();
|
||||
}
|
||||
|
||||
intptr_t Field::Offset() const {
|
||||
ASSERT(is_instance()); // Valid only for dart instance fields.
|
||||
intptr_t value = Smi::Value(raw_ptr()->value_.offset_);
|
||||
|
|
Loading…
Reference in a new issue