| Index: runtime/observatory/lib/src/service/object.dart
|
| diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
|
| index 4a7ad32de8479fc998b28ed3214c23c647e81c46..136de497f07471bd27903823a7805c71b5e5c4f4 100644
|
| --- a/runtime/observatory/lib/src/service/object.dart
|
| +++ b/runtime/observatory/lib/src/service/object.dart
|
| @@ -118,6 +118,7 @@ abstract class ServiceObject extends Observable {
|
| bool get isList => false;
|
| bool get isMap => false;
|
| bool get isTypedData => false;
|
| + bool get isRegExp => false;
|
| bool get isMirrorReference => false;
|
| bool get isWeakProperty => false;
|
| bool get isClosure => false;
|
| @@ -1875,6 +1876,7 @@ class Instance extends ServiceObject {
|
| @observable Context context; // If a closure.
|
| @observable String name; // If a Type.
|
| @observable int length; // If a List, Map or TypedData.
|
| + @observable String pattern; // If a RegExp.
|
|
|
| @observable var typeClass;
|
| @observable var fields;
|
| @@ -1886,6 +1888,10 @@ class Instance extends ServiceObject {
|
| @observable Instance key; // If a WeakProperty.
|
| @observable Instance value; // If a WeakProperty.
|
| @observable Breakpoint activationBreakpoint; // If a Closure.
|
| + @observable Function oneByteFunction; // If a RegExp.
|
| + @observable Function twoByteFunction; // If a RegExp.
|
| + @observable Function externalOneByteFunction; // If a RegExp.
|
| + @observable Function externalTwoByteFunction; // If a RegExp.
|
|
|
| bool get isAbstractType {
|
| return (kind == 'Type' || kind == 'TypeRef' ||
|
| @@ -1914,6 +1920,7 @@ class Instance extends ServiceObject {
|
| || kind == 'Float32x4List'
|
| || kind == 'Float64x2List';
|
| }
|
| + bool get isRegExp => kind == 'RegExp';
|
| bool get isMirrorReference => kind == 'MirrorReference';
|
| bool get isWeakProperty => kind == 'WeakProperty';
|
| bool get isClosure => kind == 'Closure';
|
| @@ -1938,11 +1945,17 @@ class Instance extends ServiceObject {
|
| context = map['closureContext'];
|
| name = map['name'];
|
| length = map['length'];
|
| + pattern = map['pattern'];
|
|
|
| if (mapIsRef) {
|
| return;
|
| }
|
|
|
| + oneByteFunction = map['_oneByteFunction'];
|
| + twoByteFunction = map['_twoByteFunction'];
|
| + externalOneByteFunction = map['_externalOneByteFunction'];
|
| + externalTwoByteFunction = map['_externalTwoByteFunction'];
|
| +
|
| nativeFields = map['_nativeFields'];
|
| fields = map['fields'];
|
| elements = map['elements'];
|
| @@ -2807,7 +2820,8 @@ class CodeInstruction extends Observable {
|
| }
|
| }
|
|
|
| - void _resolveJumpTarget(List<CodeInstruction> instructions) {
|
| + void _resolveJumpTarget(List<CodeInstruction> instructionsByAddressOffset,
|
| + int startAddress) {
|
| if (!_isJumpInstruction()) {
|
| return;
|
| }
|
| @@ -2815,13 +2829,8 @@ class CodeInstruction extends Observable {
|
| if (address == 0) {
|
| return;
|
| }
|
| - for (var i = 0; i < instructions.length; i++) {
|
| - var instruction = instructions[i];
|
| - if (instruction.address == address) {
|
| - jumpTarget = instruction;
|
| - return;
|
| - }
|
| - }
|
| +
|
| + jumpTarget = instructionsByAddressOffset[address - startAddress];
|
| }
|
| }
|
|
|
| @@ -2870,6 +2879,8 @@ class Code extends ServiceObject {
|
| @reflectable int startAddress = 0;
|
| @reflectable int endAddress = 0;
|
| @reflectable final instructions = new ObservableList<CodeInstruction>();
|
| + List<CodeInstruction> instructionsByAddressOffset;
|
| +
|
| @observable ProfileCode profile;
|
| final List<CodeInlineInterval> inlineIntervals =
|
| new List<CodeInlineInterval>();
|
| @@ -3008,6 +3019,8 @@ class Code extends ServiceObject {
|
| void _processDisassembly(List<String> disassembly){
|
| assert(disassembly != null);
|
| instructions.clear();
|
| + instructionsByAddressOffset = new List(endAddress - startAddress);
|
| +
|
| assert((disassembly.length % 3) == 0);
|
| for (var i = 0; i < disassembly.length; i += 3) {
|
| var address = 0; // Assume code comment.
|
| @@ -3021,37 +3034,37 @@ class Code extends ServiceObject {
|
| }
|
| var instruction = new CodeInstruction(address, pcOffset, machine, human);
|
| instructions.add(instruction);
|
| + if (disassembly[i] != '') {
|
| + // Not a code comment.
|
| + instructionsByAddressOffset[pcOffset] = instruction;
|
| + }
|
| }
|
| for (var instruction in instructions) {
|
| - instruction._resolveJumpTarget(instructions);
|
| + instruction._resolveJumpTarget(instructionsByAddressOffset, startAddress);
|
| }
|
| }
|
|
|
| - void _processDescriptor(Map d) {
|
| - var pcOffset = int.parse(d['pcOffset'], radix:16);
|
| - var address = startAddress + pcOffset;
|
| - var deoptId = d['deoptId'];
|
| - var tokenPos = d['tokenPos'];
|
| - var tryIndex = d['tryIndex'];
|
| - var kind = d['kind'].trim();
|
| - for (var instruction in instructions) {
|
| - if (instruction.address == address) {
|
| + void _processDescriptors(List<Map> descriptors) {
|
| + for (Map descriptor in descriptors) {
|
| + var pcOffset = int.parse(descriptor['pcOffset'], radix:16);
|
| + var address = startAddress + pcOffset;
|
| + var deoptId = descriptor['deoptId'];
|
| + var tokenPos = descriptor['tokenPos'];
|
| + var tryIndex = descriptor['tryIndex'];
|
| + var kind = descriptor['kind'].trim();
|
| +
|
| + var instruction = instructionsByAddressOffset[address - startAddress];
|
| + if (instruction != null) {
|
| instruction.descriptors.add(new PcDescriptor(pcOffset,
|
| deoptId,
|
| tokenPos,
|
| tryIndex,
|
| kind));
|
| - return;
|
| + } else {
|
| + Logger.root.warning(
|
| + 'Could not find instruction with pc descriptor address: $address');
|
| }
|
| }
|
| - Logger.root.warning(
|
| - 'Could not find instruction with pc descriptor address: $address');
|
| - }
|
| -
|
| - void _processDescriptors(List<Map> descriptors) {
|
| - for (Map descriptor in descriptors) {
|
| - _processDescriptor(descriptor);
|
| - }
|
| }
|
|
|
| /// Returns true if [address] is contained inside [this].
|
|
|