mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[vm/bytecode] Add context IDs to disambiguate accesses to distinct contexts
This CL adds context ID operand to AllocateContext, CloneContext, LoadContextVar and StoreContextVar bytecode instructions. The context ID will be used to create distinct Slots and disambiguate accesses to context objects corresponding to different scopes. Change-Id: I98850ab763017b71c1dcacfccaffc085bd850e00 Reviewed-on: https://dart-review.googlesource.com/c/84681 Auto-Submit: Alexander Markov <alexmarkov@google.com> Commit-Queue: Régis Crelier <regis@google.com> Reviewed-by: Régis Crelier <regis@google.com>
This commit is contained in:
parent
81d899ac30
commit
a9abc64613
|
@ -317,8 +317,8 @@ class BytecodeAssembler {
|
|||
emitWord(_encode0(Opcode.kStoreContextParent));
|
||||
}
|
||||
|
||||
void emitStoreContextVar(int rd) {
|
||||
emitWord(_encodeD(Opcode.kStoreContextVar, rd));
|
||||
void emitStoreContextVar(int ra, int rd) {
|
||||
emitWord(_encodeAD(Opcode.kStoreContextVar, ra, rd));
|
||||
}
|
||||
|
||||
void emitLoadFieldTOS(int rd) {
|
||||
|
@ -333,8 +333,8 @@ class BytecodeAssembler {
|
|||
emitWord(_encode0(Opcode.kLoadContextParent));
|
||||
}
|
||||
|
||||
void emitLoadContextVar(int rd) {
|
||||
emitWord(_encodeD(Opcode.kLoadContextVar, rd));
|
||||
void emitLoadContextVar(int ra, int rd) {
|
||||
emitWord(_encodeAD(Opcode.kLoadContextVar, ra, rd));
|
||||
}
|
||||
|
||||
void emitBooleanNegateTOS() {
|
||||
|
@ -359,12 +359,12 @@ class BytecodeAssembler {
|
|||
emitWord(_encodeA(Opcode.kSetFrame, ra));
|
||||
}
|
||||
|
||||
void emitAllocateContext(int rd) {
|
||||
emitWord(_encodeD(Opcode.kAllocateContext, rd));
|
||||
void emitAllocateContext(int ra, int rd) {
|
||||
emitWord(_encodeAD(Opcode.kAllocateContext, ra, rd));
|
||||
}
|
||||
|
||||
void emitCloneContext(int rd) {
|
||||
emitWord(_encodeD(Opcode.kCloneContext, rd));
|
||||
void emitCloneContext(int ra, int rd) {
|
||||
emitWord(_encodeAD(Opcode.kCloneContext, ra, rd));
|
||||
}
|
||||
|
||||
void emitMoveSpecial(SpecialIndex ra, int rx) {
|
||||
|
|
|
@ -173,17 +173,17 @@ const Map<Opcode, Format> BytecodeFormats = const {
|
|||
Opcode.kCreateArrayTOS: const Format(
|
||||
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
|
||||
Opcode.kAllocateContext: const Format(
|
||||
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
|
||||
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
|
||||
Opcode.kCloneContext: const Format(
|
||||
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
|
||||
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
|
||||
Opcode.kLoadContextParent: const Format(
|
||||
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
|
||||
Opcode.kStoreContextParent: const Format(
|
||||
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
|
||||
Opcode.kLoadContextVar: const Format(
|
||||
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
|
||||
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
|
||||
Opcode.kStoreContextVar: const Format(
|
||||
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
|
||||
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
|
||||
Opcode.kPushConstant: const Format(
|
||||
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
|
||||
Opcode.kPushNull: const Format(
|
||||
|
@ -347,6 +347,9 @@ const int localVariableIndexLimit = 1 << 15;
|
|||
// Captured variables are referenced using 16-bit unsigned operands.
|
||||
const int capturedVariableIndexLimit = 1 << 16;
|
||||
|
||||
// Context IDs are referenced using 8-bit unsigned operands.
|
||||
const int contextIdLimit = 1 << 8;
|
||||
|
||||
// Base class for exceptions thrown when certain limit of bytecode
|
||||
// format is exceeded.
|
||||
abstract class BytecodeLimitExceededException {}
|
||||
|
|
|
@ -634,7 +634,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
|
||||
if (locals.isCaptured(v)) {
|
||||
_genPushContextForVariable(v, currentContextLevel: currentContextLevel);
|
||||
asm.emitLoadContextVar(locals.getVarIndexInContext(v));
|
||||
asm.emitLoadContextVar(
|
||||
locals.getVarContextId(v), locals.getVarIndexInContext(v));
|
||||
} else {
|
||||
asm.emitPush(locals.getVarIndexInFrame(v));
|
||||
}
|
||||
|
@ -650,7 +651,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
// If variable is captured, context should be pushed before value.
|
||||
void _genStoreVar(VariableDeclaration variable) {
|
||||
if (locals.isCaptured(variable)) {
|
||||
asm.emitStoreContextVar(locals.getVarIndexInContext(variable));
|
||||
asm.emitStoreContextVar(locals.getVarContextId(variable),
|
||||
locals.getVarIndexInContext(variable));
|
||||
} else {
|
||||
asm.emitPopLocal(locals.getVarIndexInFrame(variable));
|
||||
}
|
||||
|
@ -1426,7 +1428,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
void _allocateContextIfNeeded() {
|
||||
final int contextSize = locals.currentContextSize;
|
||||
if (contextSize > 0) {
|
||||
asm.emitAllocateContext(contextSize);
|
||||
asm.emitAllocateContext(locals.currentContextId, contextSize);
|
||||
|
||||
if (locals.currentContextLevel > 0) {
|
||||
_genDupTOS(locals.scratchVarIndexInFrame);
|
||||
|
@ -2466,7 +2468,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
|
||||
if (locals.currentContextSize > 0) {
|
||||
asm.emitPush(locals.contextVarIndexInFrame);
|
||||
asm.emitCloneContext(locals.currentContextSize);
|
||||
asm.emitCloneContext(
|
||||
locals.currentContextId, locals.currentContextSize);
|
||||
asm.emitPopLocal(locals.contextVarIndexInFrame);
|
||||
}
|
||||
|
||||
|
@ -2849,11 +2852,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
|
|||
} else {
|
||||
asm.emitPushNull();
|
||||
}
|
||||
if (isCaptured) {
|
||||
asm.emitStoreContextVar(locals.getVarIndexInContext(node));
|
||||
} else {
|
||||
asm.emitPopLocal(locals.getVarIndexInFrame(node));
|
||||
}
|
||||
_genStoreVar(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ class LocalVariables {
|
|||
|
||||
int get currentContextSize => _currentScope.contextSize;
|
||||
int get currentContextLevel => _currentScope.contextLevel;
|
||||
int get currentContextId => _currentScope.contextId;
|
||||
|
||||
int get contextLevelAtEntry =>
|
||||
_currentFrame.contextLevelAtEntry ??
|
||||
|
@ -74,6 +75,12 @@ class LocalVariables {
|
|||
return v.scope.contextLevel;
|
||||
}
|
||||
|
||||
int getVarContextId(VariableDeclaration variable) {
|
||||
final v = _getVarDesc(variable);
|
||||
assert(v.isCaptured);
|
||||
return v.scope.contextId;
|
||||
}
|
||||
|
||||
int get closureVarIndexInFrame => getVarIndexInFrame(_currentFrame
|
||||
.closureVar ??
|
||||
(throw 'Closure variable is not declared in ${_currentFrame.function}'));
|
||||
|
@ -257,6 +264,7 @@ class Scope {
|
|||
int contextUsed = 0;
|
||||
int contextSize = 0;
|
||||
int contextLevel;
|
||||
int contextId;
|
||||
|
||||
Scope(this.parent, this.frame, this.loopDepth);
|
||||
|
||||
|
@ -699,6 +707,7 @@ class _Allocator extends RecursiveVisitor<Null> {
|
|||
|
||||
Scope _currentScope;
|
||||
Frame _currentFrame;
|
||||
int _contextIdCounter = 0;
|
||||
|
||||
_Allocator(this.locals);
|
||||
|
||||
|
@ -738,6 +747,7 @@ class _Allocator extends RecursiveVisitor<Null> {
|
|||
|
||||
assert(_currentScope.contextOwner == null);
|
||||
assert(_currentScope.contextLevel == null);
|
||||
assert(_currentScope.contextId == null);
|
||||
|
||||
final int parentContextLevel =
|
||||
_currentScope.parent != null ? _currentScope.parent.contextLevel : -1;
|
||||
|
@ -763,8 +773,13 @@ class _Allocator extends RecursiveVisitor<Null> {
|
|||
|
||||
if (_currentScope.contextOwner == _currentScope) {
|
||||
_currentScope.contextLevel = parentContextLevel + 1;
|
||||
_currentScope.contextId = _contextIdCounter++;
|
||||
if (_currentScope.contextId >= contextIdLimit) {
|
||||
throw new ContextIdOverflowException();
|
||||
}
|
||||
} else {
|
||||
_currentScope.contextLevel = _currentScope.contextOwner.contextLevel;
|
||||
_currentScope.contextId = _currentScope.contextOwner.contextId;
|
||||
}
|
||||
} else {
|
||||
_currentScope.contextLevel = parentContextLevel;
|
||||
|
@ -1147,3 +1162,5 @@ class _Allocator extends RecursiveVisitor<Null> {
|
|||
|
||||
class LocalVariableIndexOverflowException
|
||||
extends BytecodeLimitExceededException {}
|
||||
|
||||
class ContextIdOverflowException extends BytecodeLimitExceededException {}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -187,11 +187,11 @@ Bytecode (version: stable) {
|
|||
Entry 5
|
||||
CheckStack 0
|
||||
CheckFunctionTypeArgs 2, r0
|
||||
AllocateContext 1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r1
|
||||
Push r1
|
||||
Push FP[-5]
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Allocate CP#31
|
||||
StoreLocal r4
|
||||
Push r4
|
||||
|
@ -290,7 +290,7 @@ Closure CP#12 {
|
|||
Push r3
|
||||
PushInt 0
|
||||
Push r1
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
LoadTypeArgumentsField CP#15
|
||||
PushNull
|
||||
InstantiateType CP#14
|
||||
|
@ -298,7 +298,7 @@ Closure CP#12 {
|
|||
Push r3
|
||||
PushInt 1
|
||||
Push r1
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
LoadTypeArgumentsField CP#15
|
||||
PushNull
|
||||
InstantiateType CP#16
|
||||
|
@ -345,7 +345,7 @@ Closure CP#12 {
|
|||
IndirectStaticCall 1, CP#25
|
||||
Drop1
|
||||
Push r1
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
LoadTypeArgumentsField CP#15
|
||||
Push r0
|
||||
InstantiateTypeArgumentsTOS 0, CP#27
|
||||
|
@ -385,7 +385,7 @@ L2:
|
|||
StoreLocal r4
|
||||
Push r4
|
||||
Push r1
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
LoadTypeArgumentsField CP#15
|
||||
StoreFieldTOS CP#32
|
||||
Push r4
|
||||
|
@ -437,7 +437,7 @@ L2:
|
|||
StoreLocal r4
|
||||
Push r4
|
||||
Push r1
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
LoadTypeArgumentsField CP#15
|
||||
StoreFieldTOS CP#32
|
||||
Push r4
|
||||
|
@ -506,19 +506,19 @@ ConstantPool {
|
|||
Bytecode (version: stable) {
|
||||
Entry 5
|
||||
CheckStack 0
|
||||
AllocateContext 4
|
||||
AllocateContext 0, 4
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push FP[-5]
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Push r0
|
||||
PushInt 1
|
||||
StoreContextVar 1
|
||||
StoreContextVar 0, 1
|
||||
PushInt 2
|
||||
PopLocal r2
|
||||
Push r0
|
||||
PushInt 3
|
||||
StoreContextVar 2
|
||||
StoreContextVar 0, 2
|
||||
Allocate CP#10
|
||||
StoreLocal r4
|
||||
Push r4
|
||||
|
@ -550,18 +550,18 @@ Bytecode (version: stable) {
|
|||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 2
|
||||
LoadContextVar 0, 2
|
||||
PushConstant CP#27
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 1
|
||||
LoadContextVar 0, 1
|
||||
PushConstant CP#28
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
Push r0
|
||||
PushInt 42
|
||||
StoreContextVar 3
|
||||
StoreContextVar 0, 3
|
||||
Allocate CP#10
|
||||
StoreLocal r3
|
||||
Push r3
|
||||
|
@ -631,19 +631,19 @@ Closure CP#6 {
|
|||
LoadContextParent
|
||||
Push r0
|
||||
LoadContextParent
|
||||
LoadContextVar 1
|
||||
LoadContextVar 0, 1
|
||||
PushInt 2
|
||||
AddInt
|
||||
StoreContextVar 2
|
||||
StoreContextVar 0, 2
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextParent
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
InstanceCall 1, CP#8
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 1, 0
|
||||
AddInt
|
||||
StoreContextVar 1
|
||||
StoreContextVar 1, 1
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
||||
|
@ -655,7 +655,7 @@ Closure CP#0 {
|
|||
Push FP[-6]
|
||||
LoadFieldTOS CP#1
|
||||
PopLocal r0
|
||||
AllocateContext 2
|
||||
AllocateContext 1, 2
|
||||
StoreLocal r1
|
||||
Push r1
|
||||
Push r0
|
||||
|
@ -663,7 +663,7 @@ Closure CP#0 {
|
|||
PopLocal r0
|
||||
Push r0
|
||||
Push FP[-5]
|
||||
StoreContextVar 0
|
||||
StoreContextVar 1, 0
|
||||
Push FP[-5]
|
||||
PushConstant CP#3
|
||||
PushNull
|
||||
|
@ -674,19 +674,19 @@ Closure CP#0 {
|
|||
Push r0
|
||||
LoadContextParent
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 1, 0
|
||||
PushInt 1
|
||||
AddInt
|
||||
StoreContextVar 1
|
||||
StoreContextVar 0, 1
|
||||
Push r0
|
||||
LoadContextParent
|
||||
LoadContextVar 1
|
||||
LoadContextVar 0, 1
|
||||
PushInt 5
|
||||
CompareIntGt
|
||||
JumpIfFalse L1
|
||||
Push r0
|
||||
PushInt 4
|
||||
StoreContextVar 1
|
||||
StoreContextVar 1, 1
|
||||
Allocate CP#10
|
||||
StoreLocal r2
|
||||
Push r2
|
||||
|
@ -709,7 +709,7 @@ Closure CP#0 {
|
|||
InstanceCall 1, CP#20
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 1
|
||||
LoadContextVar 1, 1
|
||||
PushConstant CP#21
|
||||
IndirectStaticCall 1, CP#7
|
||||
Drop1
|
||||
|
@ -726,9 +726,9 @@ Closure CP#29 {
|
|||
LoadFieldTOS CP#1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
Push r0
|
||||
LoadContextVar 3
|
||||
LoadContextVar 0, 3
|
||||
InstanceCall 2, CP#30
|
||||
Drop1
|
||||
PushNull
|
||||
|
@ -792,11 +792,11 @@ ConstantPool {
|
|||
Bytecode (version: stable) {
|
||||
Entry 5
|
||||
CheckStack 0
|
||||
AllocateContext 1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
PushInt 0
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
PushConstant CP#0
|
||||
StoreLocal r3
|
||||
Push r3
|
||||
|
@ -815,7 +815,7 @@ Bytecode (version: stable) {
|
|||
PushConstant CP#3
|
||||
IndirectStaticCall 2, CP#1
|
||||
PopLocal r4
|
||||
AllocateContext 1
|
||||
AllocateContext 1, 1
|
||||
StoreLocal r1
|
||||
Push r1
|
||||
Push r0
|
||||
|
@ -823,11 +823,11 @@ Bytecode (version: stable) {
|
|||
PopLocal r0
|
||||
Push r0
|
||||
PushInt 0
|
||||
StoreContextVar 0
|
||||
StoreContextVar 1, 0
|
||||
L2:
|
||||
CheckStack 1
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 1, 0
|
||||
PushInt 10
|
||||
CompareIntLt
|
||||
JumpIfFalse L1
|
||||
|
@ -872,15 +872,15 @@ L2:
|
|||
InstanceCall 2, CP#24
|
||||
Drop1
|
||||
Push r0
|
||||
CloneContext 1
|
||||
CloneContext 1, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 1, 0
|
||||
PushInt 1
|
||||
AddInt
|
||||
StoreLocal r3
|
||||
StoreContextVar 0
|
||||
StoreContextVar 1, 0
|
||||
Push r3
|
||||
Drop1
|
||||
Jump L2
|
||||
|
@ -928,10 +928,10 @@ Closure CP#4 {
|
|||
LoadFieldTOS CP#5
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 1, 0
|
||||
Push r0
|
||||
LoadContextParent
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
AddInt
|
||||
ReturnTOS
|
||||
|
||||
|
@ -954,9 +954,9 @@ Closure CP#19 {
|
|||
Push FP[-5]
|
||||
Push r0
|
||||
LoadContextParent
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
AddInt
|
||||
StoreContextVar 0
|
||||
StoreContextVar 1, 0
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
||||
|
@ -984,12 +984,12 @@ L2:
|
|||
Push r2
|
||||
InstanceCall 1, CP#2
|
||||
JumpIfFalse L1
|
||||
AllocateContext 1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push r2
|
||||
InstanceCall 1, CP#3
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Allocate CP#8
|
||||
StoreLocal r4
|
||||
Push r4
|
||||
|
@ -1012,7 +1012,7 @@ L2:
|
|||
InstanceCall 1, CP#18
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#19
|
||||
IndirectStaticCall 1, CP#0
|
||||
Drop1
|
||||
|
@ -1054,10 +1054,10 @@ Closure CP#4 {
|
|||
PopLocal r0
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushInt 1
|
||||
AddInt
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
||||
|
@ -1095,11 +1095,11 @@ ConstantPool {
|
|||
Bytecode (version: stable) {
|
||||
Entry 3
|
||||
CheckStack 0
|
||||
AllocateContext 1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push FP[-5]
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Push FP[-5]
|
||||
PushConstant CP#0
|
||||
Push FP[-6]
|
||||
|
@ -1155,7 +1155,7 @@ Closure CP#4 {
|
|||
LoadFieldTOS CP#5
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
ReturnTOS
|
||||
|
||||
}
|
||||
|
@ -1167,11 +1167,11 @@ Closure CP#4 {
|
|||
Bytecode (version: stable) {
|
||||
Entry 4
|
||||
CheckStack 0
|
||||
AllocateContext 1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
PushInt 5
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Allocate CP#7
|
||||
StoreLocal r3
|
||||
Push r3
|
||||
|
@ -1195,7 +1195,7 @@ Bytecode (version: stable) {
|
|||
InstanceCall 2, CP#18
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
ReturnTOS
|
||||
}
|
||||
ConstantPool {
|
||||
|
@ -1234,10 +1234,10 @@ Closure CP#0 {
|
|||
Drop1
|
||||
Push r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
Push FP[-5]
|
||||
AddInt
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
PushNull
|
||||
ReturnTOS
|
||||
|
||||
|
|
|
@ -229,17 +229,17 @@ ConstantPool {
|
|||
Bytecode (version: stable) {
|
||||
Entry 7
|
||||
CheckStack 0
|
||||
AllocateContext 3
|
||||
AllocateContext 0, 3
|
||||
PopLocal r0
|
||||
Push r0
|
||||
PushInt 1
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Push r0
|
||||
PopLocal r2
|
||||
Try #0 start:
|
||||
Push r0
|
||||
PushInt 2
|
||||
StoreContextVar 1
|
||||
StoreContextVar 0, 1
|
||||
Allocate CP#9
|
||||
StoreLocal r5
|
||||
Push r5
|
||||
|
@ -262,7 +262,7 @@ Try #0 start:
|
|||
InstanceCall 1, CP#19
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 1
|
||||
LoadContextVar 0, 1
|
||||
PushConstant CP#20
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
|
@ -278,7 +278,7 @@ Try #0 handler:
|
|||
PopLocal r4
|
||||
Push r0
|
||||
Push r3
|
||||
StoreContextVar 2
|
||||
StoreContextVar 0, 2
|
||||
PushNull
|
||||
PushInt 4
|
||||
CreateArrayTOS
|
||||
|
@ -298,7 +298,7 @@ Try #0 handler:
|
|||
Push r5
|
||||
PushInt 3
|
||||
Push r0
|
||||
LoadContextVar 2
|
||||
LoadContextVar 0, 2
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#23
|
||||
IndirectStaticCall 1, CP#4
|
||||
|
@ -397,13 +397,13 @@ Try #0 handler:
|
|||
Push r2
|
||||
PopLocal r4
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#7
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
Push r0
|
||||
PushInt 3
|
||||
StoreContextVar 1
|
||||
StoreContextVar 0, 1
|
||||
Jump L1
|
||||
L1:
|
||||
PushNull
|
||||
|
@ -457,7 +457,7 @@ Try #0 handler:
|
|||
Push r5
|
||||
PushInt 3
|
||||
Push r0
|
||||
LoadContextVar 2
|
||||
LoadContextVar 0, 2
|
||||
StoreIndexedTOS
|
||||
PushConstant CP#33
|
||||
IndirectStaticCall 1, CP#4
|
||||
|
@ -692,13 +692,13 @@ ConstantPool {
|
|||
Bytecode (version: stable) {
|
||||
Entry 9
|
||||
CheckStack 0
|
||||
AllocateContext 2
|
||||
AllocateContext 0, 2
|
||||
PopLocal r0
|
||||
Push r0
|
||||
Push FP[-5]
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PopLocal r2
|
||||
Push r2
|
||||
PushInt 1
|
||||
|
@ -719,7 +719,7 @@ Try #0 start:
|
|||
Drop1
|
||||
Push r0
|
||||
PushInt 3
|
||||
StoreContextVar 1
|
||||
StoreContextVar 0, 1
|
||||
Push r0
|
||||
PopLocal r5
|
||||
Try #1 start:
|
||||
|
@ -852,12 +852,12 @@ Closure CP#8 {
|
|||
LoadFieldTOS CP#9
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
Push r0
|
||||
LoadContextVar 1
|
||||
LoadContextVar 0, 1
|
||||
PushConstant CP#12
|
||||
IndirectStaticCall 1, CP#4
|
||||
Drop1
|
||||
|
@ -905,11 +905,11 @@ Closure CP#8 {
|
|||
Bytecode (version: stable) {
|
||||
Entry 6
|
||||
CheckStack 0
|
||||
AllocateContext 1
|
||||
AllocateContext 0, 1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
PushInt 11
|
||||
StoreContextVar 0
|
||||
StoreContextVar 0, 0
|
||||
PushNull
|
||||
PopLocal r2
|
||||
Push r0
|
||||
|
@ -942,7 +942,7 @@ Try #0 handler:
|
|||
MoveSpecial exception, r3
|
||||
MoveSpecial stackTrace, r4
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#26
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
@ -956,7 +956,7 @@ L1:
|
|||
Push r3
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#28
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
@ -1011,7 +1011,7 @@ Closure CP#0 {
|
|||
LoadFieldTOS CP#1
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#4
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
@ -1046,7 +1046,7 @@ Try #1 handler:
|
|||
MoveSpecial exception, r4
|
||||
MoveSpecial stackTrace, r5
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#10
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
@ -1057,7 +1057,7 @@ L2:
|
|||
Push r4
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#11
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
@ -1082,7 +1082,7 @@ Try #2 handler:
|
|||
MoveSpecial exception, r4
|
||||
MoveSpecial stackTrace, r5
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#13
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
@ -1093,7 +1093,7 @@ L3:
|
|||
Push r4
|
||||
PopLocal r0
|
||||
Push r0
|
||||
LoadContextVar 0
|
||||
LoadContextVar 0, 0
|
||||
PushConstant CP#14
|
||||
IndirectStaticCall 1, CP#3
|
||||
Drop1
|
||||
|
|
|
@ -34,7 +34,8 @@ T* PutIfAbsent(Thread* thread,
|
|||
return array->At(index);
|
||||
}
|
||||
|
||||
LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t index) {
|
||||
LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t context_id,
|
||||
intptr_t index) {
|
||||
return PutIfAbsent<LocalVariable>(
|
||||
thread(), &dummy_captured_vars_, index, [&]() {
|
||||
Zone* const Z = thread()->zone();
|
||||
|
@ -52,6 +53,7 @@ LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t index) {
|
|||
}
|
||||
|
||||
const GrowableArray<LocalVariable*>& CompilerState::GetDummyContextVariables(
|
||||
intptr_t context_id,
|
||||
intptr_t num_context_variables) {
|
||||
return PutIfAbsent<LocalScope>(
|
||||
thread(), &dummy_scopes_, num_context_variables,
|
||||
|
@ -63,7 +65,7 @@ const GrowableArray<LocalVariable*>& CompilerState::GetDummyContextVariables(
|
|||
scope->set_context_level(0);
|
||||
|
||||
for (intptr_t i = 0; i < num_context_variables; i++) {
|
||||
LocalVariable* var = GetDummyCapturedVariable(i);
|
||||
LocalVariable* var = GetDummyCapturedVariable(context_id, i);
|
||||
scope->AddVariable(var);
|
||||
scope->AddContextVariable(var);
|
||||
}
|
||||
|
|
|
@ -87,16 +87,20 @@ class CompilerState : public StackResource {
|
|||
void set_slot_cache(SlotCache* cache) { slot_cache_ = cache; }
|
||||
|
||||
// Create a dummy list of local variables representing a context object
|
||||
// with the given number of captured variables.
|
||||
// with the given number of captured variables and given ID.
|
||||
//
|
||||
// Used during bytecode to IL translation because AllocateContext and
|
||||
// CloneContext IL instructions need a list of local varaibles and bytecode
|
||||
// does not record this information.
|
||||
//
|
||||
// TODO(vegorov): create context classes for distinct context IDs and
|
||||
// populate them with slots without creating variables.
|
||||
const GrowableArray<LocalVariable*>& GetDummyContextVariables(
|
||||
intptr_t context_id,
|
||||
intptr_t num_context_variables);
|
||||
|
||||
// Create a dummy LocalVariable that represents a captured local variable
|
||||
// at the given index.
|
||||
// at the given index in the context with given ID.
|
||||
//
|
||||
// Used during bytecode to IL translation because StoreInstanceField and
|
||||
// LoadField IL instructions need Slot, which can only be created from a
|
||||
|
@ -104,7 +108,9 @@ class CompilerState : public StackResource {
|
|||
//
|
||||
// This function returns the same variable when it is called with the
|
||||
// same index.
|
||||
LocalVariable* GetDummyCapturedVariable(intptr_t index);
|
||||
//
|
||||
// TODO(vegorov): disambiguate slots for different context IDs.
|
||||
LocalVariable* GetDummyCapturedVariable(intptr_t context_id, intptr_t index);
|
||||
|
||||
private:
|
||||
CHA cha_;
|
||||
|
|
|
@ -781,8 +781,11 @@ void BytecodeFlowGraphBuilder::BuildAllocateContext() {
|
|||
UNIMPLEMENTED(); // TODO(alexmarkov): interpreter
|
||||
}
|
||||
|
||||
const intptr_t context_id = DecodeOperandA().value();
|
||||
const intptr_t num_context_vars = DecodeOperandD().value();
|
||||
|
||||
auto& context_variables = CompilerState::Current().GetDummyContextVariables(
|
||||
DecodeOperandD().value());
|
||||
context_id, num_context_vars);
|
||||
code_ += B->AllocateContext(context_variables);
|
||||
}
|
||||
|
||||
|
@ -792,8 +795,11 @@ void BytecodeFlowGraphBuilder::BuildCloneContext() {
|
|||
}
|
||||
|
||||
LoadStackSlots(1);
|
||||
const intptr_t context_id = DecodeOperandA().value();
|
||||
const intptr_t num_context_vars = DecodeOperandD().value();
|
||||
|
||||
auto& context_variables = CompilerState::Current().GetDummyContextVariables(
|
||||
DecodeOperandD().value());
|
||||
context_id, num_context_vars);
|
||||
CloneContextInstr* clone_instruction = new (Z) CloneContextInstr(
|
||||
TokenPosition::kNoSource, Pop(), context_variables, B->GetNextDeoptId());
|
||||
code_ <<= clone_instruction;
|
||||
|
@ -885,12 +891,11 @@ void BytecodeFlowGraphBuilder::BuildStoreContextVar() {
|
|||
}
|
||||
|
||||
LoadStackSlots(2);
|
||||
Operand var_index = DecodeOperandD();
|
||||
const intptr_t context_id = DecodeOperandA().value();
|
||||
const intptr_t var_index = DecodeOperandD().value();
|
||||
|
||||
// TODO(alexmarkov) provide context_id in bytecode to disambiguate variables
|
||||
// in different contexts
|
||||
auto var =
|
||||
CompilerState::Current().GetDummyCapturedVariable(var_index.value());
|
||||
CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
|
||||
code_ += B->StoreInstanceField(
|
||||
position_, Slot::GetContextVariableSlotFor(thread(), *var));
|
||||
}
|
||||
|
@ -901,12 +906,11 @@ void BytecodeFlowGraphBuilder::BuildLoadContextVar() {
|
|||
}
|
||||
|
||||
LoadStackSlots(1);
|
||||
Operand var_index = DecodeOperandD();
|
||||
const intptr_t context_id = DecodeOperandA().value();
|
||||
const intptr_t var_index = DecodeOperandD().value();
|
||||
|
||||
// TODO(alexmarkov) provide context_id in bytecode to disambiguate variables
|
||||
// in different contexts
|
||||
auto var =
|
||||
CompilerState::Current().GetDummyCapturedVariable(var_index.value());
|
||||
CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
|
||||
code_ += B->LoadNativeField(Slot::GetContextVariableSlotFor(thread(), *var));
|
||||
}
|
||||
|
||||
|
|
|
@ -155,13 +155,18 @@ namespace dart {
|
|||
//
|
||||
// Allocate array of length SP[0] with type arguments SP[-1].
|
||||
//
|
||||
// - AllocateContext D
|
||||
// - AllocateContext A, D
|
||||
//
|
||||
// Allocate Context object assuming for D context variables.
|
||||
// Allocate Context object holding D context variables.
|
||||
// A is a static ID of the context. Static ID of a context may be used to
|
||||
// disambiguate accesses to different context objects.
|
||||
// Context objects with the same ID should have the same number of
|
||||
// context variables.
|
||||
//
|
||||
// - CloneContext D
|
||||
// - CloneContext A, D
|
||||
//
|
||||
// Clone Context object stored in TOS assuming it has D context variables.
|
||||
// Clone Context object SP[0] holding D context variables.
|
||||
// A is a static ID of the context. Cloned context has the same ID.
|
||||
//
|
||||
// - LoadContextParent
|
||||
//
|
||||
|
@ -171,13 +176,15 @@ namespace dart {
|
|||
//
|
||||
// Store context SP[0] into `parent` field of context SP[-1].
|
||||
//
|
||||
// - LoadContextVar D
|
||||
// - LoadContextVar A, D
|
||||
//
|
||||
// Load value from context SP[0] at index D.
|
||||
// A is a static ID of the context.
|
||||
//
|
||||
// - StoreContextVar D
|
||||
// - StoreContextVar A, D
|
||||
//
|
||||
// Store value SP[0] into context SP[-1] at index D.
|
||||
// A is a static ID of the context.
|
||||
//
|
||||
// - PushConstant D
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue