diff options
author | Ian Zerny <zerny@google.com> | 2017-07-03 15:49:19 +0200 |
---|---|---|
committer | Ian Zerny <zerny@google.com> | 2017-07-03 15:49:19 +0200 |
commit | 3d4e8f27290151539ea30a2be65872001a9b837d (patch) | |
tree | c677bafc71e909762d8b91c886ada3da44e4be68 /src/main/java/com/android/tools/r8/ir | |
parent | 5cbf5fab13e70af8a5f95f97555761a834db315e (diff) | |
download | r8-3d4e8f27290151539ea30a2be65872001a9b837d.tar.gz |
Replace DebugLocalRead instruction by annotations directly on instructions.
This is in preperation for emitting exact local changes which requires that the
scope-end of a local is attached to the instruction at which it ends. The use of
debug-local read instructions did not allow this for, eg, exiting instrucitons.
R=ager, sgjesse, shertz
Bug: 63243012
Change-Id: I4423452089180654afba982f42f07cf06f757791
Diffstat (limited to 'src/main/java/com/android/tools/r8/ir')
12 files changed, 190 insertions, 158 deletions
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java index 38291549f..b9508b591 100644 --- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java +++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java @@ -541,6 +541,9 @@ public class BasicBlock { for (Value value : instruction.inValues) { value.removeUser(instruction); } + for (Value value : instruction.getDebugValues()) { + value.removeDebugUser(instruction); + } Value previousLocalValue = instruction.getPreviousLocalValue(); if (previousLocalValue != null) { previousLocalValue.removeDebugUser(instruction); diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java index 8e019ccf2..70675cbc5 100644 --- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java +++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java @@ -106,6 +106,9 @@ public class BasicBlockInstructionIterator implements InstructionIterator, Instr Value value = current.inValues().get(i); value.removeUser(current); } + for (Value value : current.getDebugValues()) { + value.removeDebugUser(current); + } Value previousLocalValue = current.getPreviousLocalValue(); if (previousLocalValue != null) { previousLocalValue.removeDebugUser(current); @@ -135,12 +138,29 @@ public class BasicBlockInstructionIterator implements InstructionIterator, Instr assert newInstruction.outValue() != null; current.outValue().replaceUsers(newInstruction.outValue()); } + for (Value value : current.getDebugValues()) { + replaceInstructionInList(current, newInstruction, value.getDebugLocalStarts()); + replaceInstructionInList(current, newInstruction, value.getDebugLocalEnds()); + value.removeDebugUser(current); + newInstruction.addDebugValue(value); + } newInstruction.setBlock(block); listIterator.remove(); listIterator.add(newInstruction); current.clearBlock(); } + private static void replaceInstructionInList( + Instruction instruction, + Instruction newInstruction, + List<Instruction> instructions) { + for (int i = 0; i < instructions.size(); i++) { + if (instructions.get(i) == instruction) { + instructions.set(i, newInstruction); + } + } + } + private BasicBlock peekPrevious(ListIterator<BasicBlock> blocksIterator) { BasicBlock block = blocksIterator.previous(); blocksIterator.next(); diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java deleted file mode 100644 index f1a6d021f..000000000 --- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. -package com.android.tools.r8.ir.code; - -import com.android.tools.r8.dex.Constants; -import com.android.tools.r8.errors.Unreachable; -import com.android.tools.r8.ir.conversion.DexBuilder; -import com.android.tools.r8.utils.InternalOptions; - -/** - * Instruction reading an SSA value with attached local information. - * - * This instruction ensures that a value with a local is kept alive until at least this read. - * - * This instruction must not be considered dead until live-ranges have been computed for locals - * after which it will be removed. - */ -public class DebugLocalRead extends Instruction { - - public DebugLocalRead(Value src) { - super(null, src); - assert src.getLocalInfo() != null; - } - - public Value src() { - return inValues.get(0); - } - - @Override - public boolean isDebugLocalRead() { - return true; - } - - @Override - public DebugLocalRead asDebugLocalRead() { - return this; - } - - @Override - public boolean identicalNonValueParts(Instruction other) { - assert other.isDebugLocalRead(); - return true; - } - - @Override - public int compareNonValueParts(Instruction other) { - assert other.isDebugLocalRead(); - return 0; - } - - @Override - public boolean canBeDeadCode(IRCode code, InternalOptions options) { - return false; - } - - @Override - public void buildDex(DexBuilder builder) { - throw new Unreachable(); - } - - @Override - public int maxInValueRegister() { - return Constants.U16BIT_MAX; - } - - @Override - public int maxOutValueRegister() { - throw new Unreachable(); - } - - public void addDebugLocalStart() { - src().addDebugLocalStart(this); - } - - public void addDebugLocalEnd() { - src().addDebugLocalEnd(this); - } -} diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java index 442fb6d23..a96b67361 100644 --- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java +++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java @@ -6,13 +6,13 @@ package com.android.tools.r8.ir.code; /** * Instruction introducing an SSA value with attached local information. * - * All instructions may have attached local information (defined as the local information of their - * outgoing value). This instruction is needed to mark a transition of an existing value (with a - * possible local attached) to a new value that has a local (possibly the same one). If all ingoing - * values end up having the same local this can be safely removed. + * <p>All instructions may have attached local information (defined as the local information of + * their outgoing value). This instruction is needed to mark a transition of an existing value (with + * a possible local attached) to a new value that has a local (possibly the same one). If all + * ingoing values end up having the same local this can be safely removed. * - * For valid debug info, this instruction should have at least one user, namely a DebugLocalRead - * denoting the end of its range, and thus it should be live. + * <p>For valid debug info, this instruction should have at least one debug user, denoting the end + * of its range, and thus it should be live. */ public class DebugLocalWrite extends Move { diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java index 8506160a9..b98d857b8 100644 --- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java +++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java @@ -205,7 +205,8 @@ public class IRCode { } if (value.debugUsers() != null) { for (Instruction debugUser : value.debugUsers()) { - assert debugUser.getPreviousLocalValue() == value; + assert debugUser.getPreviousLocalValue() == value + || debugUser.getDebugValues().contains(value); } } return true; diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java index ae4fd671a..f0ff57cb3 100644 --- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java +++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java @@ -15,6 +15,7 @@ import com.android.tools.r8.utils.CfgPrinter; import com.android.tools.r8.utils.InternalOptions; import com.android.tools.r8.utils.StringUtils; import com.android.tools.r8.utils.StringUtils.BraceType; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.List; @@ -24,6 +25,7 @@ public abstract class Instruction { protected final List<Value> inValues = new ArrayList<>(); private BasicBlock block = null; private int number = -1; + private List<Value> debugValues = null; protected Instruction(Value outValue) { setOutValue(outValue); @@ -70,11 +72,23 @@ public abstract class Instruction { } } + public void addDebugValue(Value value) { + assert value.getLocalInfo() != null; + if (debugValues == null) { + debugValues = new ArrayList<>(); + } + debugValues.add(value); + value.addDebugUser(this); + } + public static void clearUserInfo(Instruction instruction) { if (instruction.outValue != null) { instruction.outValue.clearUsersInfo(); } instruction.inValues.forEach(Value::clearUsersInfo); + if (instruction.debugValues != null) { + instruction.debugValues.forEach(Value::clearUsersInfo); + } } public final MoveType outType() { @@ -92,6 +106,29 @@ public abstract class Instruction { } } + public void replaceDebugPhi(Phi phi, Value value) { + if (debugValues != null) { + for (int i = 0; i < debugValues.size(); i++) { + if (phi == debugValues.get(i)) { + if (value.getLocalInfo() == null) { + debugValues.remove(i); + } else { + debugValues.set(i, value); + value.addDebugUser(this); + } + } + } + } + if (phi == getPreviousLocalValue()) { + if (value.getDebugInfo() == null) { + replacePreviousLocalValue(null); + } else { + replacePreviousLocalValue(value); + value.addDebugUser(this); + } + } + } + /** * Returns the basic block containing this instruction. */ @@ -297,6 +334,10 @@ public abstract class Instruction { return outValue == null ? null : outValue.getPreviousLocalValue(); } + public List<Value> getDebugValues() { + return debugValues != null ? debugValues : ImmutableList.of(); + } + public void replacePreviousLocalValue(Value value) { outValue.replacePreviousLocalValue(value); } @@ -672,7 +713,6 @@ public abstract class Instruction { public boolean isDebugInstruction() { return isDebugPosition() || isDebugLocalWrite() - || isDebugLocalRead() || isDebugLocalUninitialized(); } @@ -700,14 +740,6 @@ public abstract class Instruction { return null; } - public boolean isDebugLocalRead() { - return false; - } - - public DebugLocalRead asDebugLocalRead() { - return null; - } - public boolean isInvokeMethod() { return false; } diff --git a/src/main/java/com/android/tools/r8/ir/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java index de44e83be..cef139421 100644 --- a/src/main/java/com/android/tools/r8/ir/code/Phi.java +++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java @@ -203,14 +203,7 @@ public class Phi extends Value { } if (debugUsers() != null) { for (Instruction user : debugUsers()) { - if (this == user.getPreviousLocalValue()) { - if (same.getDebugInfo() == null) { - user.replacePreviousLocalValue(null); - } else { - user.replacePreviousLocalValue(same); - same.addDebugUser(user); - } - } + user.replaceDebugPhi(this, same); } } // If IR construction is taking place, update the definition users. diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java index f208d49f8..92bb7b20a 100644 --- a/src/main/java/com/android/tools/r8/ir/code/Value.java +++ b/src/main/java/com/android/tools/r8/ir/code/Value.java @@ -40,8 +40,8 @@ public class Value { final DebugLocalInfo local; Value previousLocalValue; Set<Instruction> debugUsers = new HashSet<>(); - List<DebugLocalRead> localStarts = new ArrayList<>(); - List<DebugLocalRead> localEnds = new ArrayList<>(); + List<Instruction> localStarts = new ArrayList<>(); + List<Instruction> localEnds = new ArrayList<>(); DebugData(DebugInfo info) { this(info.local, info.previousLocalValue); @@ -115,20 +115,20 @@ public class Value { } } - public List<DebugLocalRead> getDebugLocalStarts() { + public List<Instruction> getDebugLocalStarts() { return debugData.localStarts; } - public List<DebugLocalRead> getDebugLocalEnds() { + public List<Instruction> getDebugLocalEnds() { return debugData.localEnds; } - public void addDebugLocalStart(DebugLocalRead start) { + public void addDebugLocalStart(Instruction start) { assert start != null; debugData.localStarts.add(start); } - public void addDebugLocalEnd(DebugLocalRead end) { + public void addDebugLocalEnd(Instruction end) { assert end != null; debugData.localEnds.add(end); } @@ -253,7 +253,6 @@ public class Value { if (isUninitializedLocal()) { return; } - assert !debugData.debugUsers.contains(user); debugData.debugUsers.add(user); } @@ -307,6 +306,13 @@ public class Value { } if (debugData != null) { for (Instruction user : debugUsers()) { + user.getDebugValues().replaceAll(v -> { + if (v == this) { + newValue.addDebugUser(user); + return newValue; + } + return v; + }); if (user.getPreviousLocalValue() == this) { newValue.addDebugUser(user); user.replacePreviousLocalValue(newValue); @@ -387,8 +393,11 @@ public class Value { builder.append(constNumber.getRawValue()); } } + if (isConstant && hasLocalInfo) { + builder.append(", "); + } if (hasLocalInfo) { - builder.append(", ").append(getLocalInfo()); + builder.append(getLocalInfo()); } builder.append(")"); } diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java index fba48c95c..8aaac95df 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java @@ -34,7 +34,6 @@ import com.android.tools.r8.ir.code.ConstClass; import com.android.tools.r8.ir.code.ConstNumber; import com.android.tools.r8.ir.code.ConstString; import com.android.tools.r8.ir.code.ConstType; -import com.android.tools.r8.ir.code.DebugLocalRead; import com.android.tools.r8.ir.code.DebugLocalUninitialized; import com.android.tools.r8.ir.code.DebugLocalWrite; import com.android.tools.r8.ir.code.DebugPosition; @@ -82,11 +81,11 @@ import com.android.tools.r8.utils.InternalOptions; import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap; import it.unimi.dsi.fastutil.ints.Int2ReferenceMap; import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap; +import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntArraySet; import it.unimi.dsi.fastutil.ints.IntIterator; -import it.unimi.dsi.fastutil.ints.IntSet; -import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import it.unimi.dsi.fastutil.ints.IntSet; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -266,6 +265,11 @@ public class IRBuilder { private final InternalOptions options; + // Pending local changes. + private List<Value> debugLocalStarts = new ArrayList<>(); + private List<Value> debugLocalReads = new ArrayList<>(); + private List<Value> debugLocalEnds = new ArrayList<>(); + public IRBuilder(DexEncodedMethod method, SourceCode source, InternalOptions options) { this(method, source, new ValueNumberGenerator(), options); } @@ -517,23 +521,13 @@ public class IRBuilder { // We cannot shortcut if the local is defined by a phi as it could end up being trivial. addDebugLocalWrite(moveType, register, in); } else { - DebugLocalRead read = addDebugLocalRead(register, local); - if (read != null) { - read.addDebugLocalStart(); + Value value = getLocalValue(register, local); + if (value != null) { + debugLocalStarts.add(value); } } } - public void addDebugLocalEnd(int register, DebugLocalInfo local) { - if (!options.debug) { - return; - } - DebugLocalRead read = addDebugLocalRead(register, local); - if (read != null) { - read.addDebugLocalEnd(); - } - } - private void addDebugLocalWrite(MoveType type, int dest, Value in) { Value out = writeRegister(dest, type, ThrowingInfo.NO_THROW); DebugLocalWrite write = new DebugLocalWrite(out, in); @@ -541,10 +535,7 @@ public class IRBuilder { addInstruction(write); } - public DebugLocalRead addDebugLocalRead(int register, DebugLocalInfo local) { - if (!options.debug) { - return null; - } + private Value getLocalValue(int register, DebugLocalInfo local) { assert local != null; assert local == getCurrentLocal(register); MoveType moveType = MoveType.fromDexType(local.type); @@ -555,10 +546,27 @@ public class IRBuilder { return null; } assert in.getLocalInfo() == local; - DebugLocalRead readLocal = new DebugLocalRead(in); - assert !readLocal.instructionTypeCanThrow(); - addInstruction(readLocal); - return readLocal; + return in; + } + + public void addDebugLocalRead(int register, DebugLocalInfo local) { + if (!options.debug) { + return; + } + Value value = getLocalValue(register, local); + if (value != null) { + debugLocalReads.add(value); + } + } + + public void addDebugLocalEnd(int register, DebugLocalInfo local) { + if (!options.debug) { + return; + } + Value value = getLocalValue(register, local); + if (value != null) { + debugLocalEnds.add(value); + } } public void addAdd(NumericType type, int dest, int left, int right) { @@ -1549,6 +1557,7 @@ public class IRBuilder { // Private instruction helpers. private void addInstruction(Instruction ir) { + attachLocalChanges(ir); if (currentDebugPosition != null && !ir.isMoveException()) { flushCurrentDebugPosition(); } @@ -1574,6 +1583,29 @@ public class IRBuilder { } } + private void attachLocalChanges(Instruction ir) { + if (!options.debug) { + return; + } + if (debugLocalStarts.isEmpty() && debugLocalReads.isEmpty() && debugLocalEnds.isEmpty()) { + return; + } + for (Value debugLocalStart : debugLocalStarts) { + ir.addDebugValue(debugLocalStart); + debugLocalStart.addDebugLocalStart(ir); + } + for (Value debugLocalRead : debugLocalReads) { + ir.addDebugValue(debugLocalRead); + } + for (Value debugLocalEnd : debugLocalEnds) { + ir.addDebugValue(debugLocalEnd); + debugLocalEnd.addDebugLocalEnd(ir); + } + debugLocalStarts.clear(); + debugLocalReads.clear(); + debugLocalEnds.clear(); + } + // Package (ie, SourceCode accessed) helpers. // Ensure there is a block starting at offset. @@ -1680,8 +1712,7 @@ public class IRBuilder { private void closeCurrentBlockWithFallThrough(BasicBlock nextBlock) { assert currentBlock != null; - flushCurrentDebugPosition(); - currentBlock.add(new Goto()); + addInstruction(new Goto()); if (currentBlock.hasCatchSuccessor(nextBlock)) { needGotoToCatchBlocks.add(new BasicBlock.Pair(currentBlock, nextBlock)); } else { @@ -1731,6 +1762,12 @@ public class IRBuilder { } Goto gotoExit = new Goto(); gotoExit.setBlock(block); + if (options.debug) { + for (Value value : ret.getDebugValues()) { + gotoExit.addDebugValue(value); + value.removeDebugUser(ret); + } + } instructions.set(instructions.size() - 1, gotoExit); block.link(normalExitBlock); gotoExit.setTarget(normalExitBlock); @@ -1934,6 +1971,7 @@ public class IRBuilder { // Stack-trace support requires position information in both debug and release mode. flushCurrentDebugPosition(); currentDebugPosition = new DebugPosition(line, file); + attachLocalChanges(currentDebugPosition); } private void flushCurrentDebugPosition() { diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java index dd6832284..a2c1cbdf1 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java @@ -433,14 +433,14 @@ public class JarSourceCode implements SourceCode { preInstructionState = state.toString(); } - build(insn, builder); - // Process local-variable end scopes if this instruction is not a control-flow instruction. // For control-flow instructions, processing takes place before closing their respective blocks. if (!isControlFlowInstruction(insn)) { processLocalVariableEnd(insn, builder); } + build(insn, builder); + if (Log.ENABLED && !(insn instanceof LineNumberNode)) { int offset = getOffset(insn); if (insn instanceof LabelNode) { diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java index b25291525..b683f3a30 100644 --- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java +++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java @@ -53,12 +53,14 @@ public class DeadCodeRemover { } } - // Add all blocks from where the in-values to the instruction originates. + // Add all blocks from where the in/debug-values to the instruction originates. private static void updateWorklist(Queue<BasicBlock> worklist, Instruction instruction) { for (Value inValue : instruction.inValues()) { updateWorklist(worklist, inValue); } - + for (Value debugValue : instruction.getDebugValues()) { + updateWorklist(worklist, debugValue); + } Value previousLocalValue = instruction.getPreviousLocalValue(); if (previousLocalValue != null) { updateWorklist(worklist, previousLocalValue); diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java index 2eae8e7c5..9d303cfa5 100644 --- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java +++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java @@ -289,11 +289,6 @@ public class LinearScanRegisterAllocator implements RegisterAllocator { Iterator<Instruction> instructionIterator = block.getInstructions().iterator(); while (instructionIterator.hasNext()) { Instruction instruction = instructionIterator.next(); - // Remove any local-read instructions now that live ranges are computed. - if (instruction.isDebugLocalRead()) { - instructionIterator.remove(); - continue; - } if (!instruction.isDebugPosition()) { continue; } @@ -1674,10 +1669,16 @@ public class LinearScanRegisterAllocator implements RegisterAllocator { live.add(use); } } - Value use = instruction.getPreviousLocalValue(); - if (use != null) { - assert use.needsRegister(); - live.add(use); + if (options.debug) { + for (Value use : instruction.getDebugValues()) { + assert use.needsRegister(); + live.add(use); + } + Value use = instruction.getPreviousLocalValue(); + if (use != null) { + assert use.needsRegister(); + live.add(use); + } } } for (Phi phi : block.getPhis()) { @@ -1794,15 +1795,27 @@ public class LinearScanRegisterAllocator implements RegisterAllocator { new LiveIntervalsUse(instruction.getNumber(), instruction.maxInValueRegister())); } } - Value use = instruction.getPreviousLocalValue(); - if (use != null) { - assert use.needsRegister(); - if (!live.contains(use)) { - live.add(use); - addLiveRange(use, block, instruction.getNumber()); + if (options.debug) { + int number = instruction.getNumber(); + for (Value use : instruction.getDebugValues()) { + assert use.needsRegister(); + if (!live.contains(use)) { + live.add(use); + addLiveRange(use, block, number); + } + LiveIntervals useIntervals = use.getLiveIntervals(); + useIntervals.addUse(new LiveIntervalsUse(number, Constants.U16BIT_MAX)); + } + Value use = instruction.getPreviousLocalValue(); + if (use != null) { + assert use.needsRegister(); + if (!live.contains(use)) { + live.add(use); + addLiveRange(use, block, number); + } + LiveIntervals useIntervals = use.getLiveIntervals(); + useIntervals.addUse(new LiveIntervalsUse(number, Constants.U16BIT_MAX)); } - LiveIntervals useIntervals = use.getLiveIntervals(); - useIntervals.addUse(new LiveIntervalsUse(instruction.getNumber(), Constants.U16BIT_MAX)); } } } |