mirror of
https://github.com/dart-lang/sdk
synced 2024-10-05 20:15:01 +00:00
Support Types in instance-ref/instance-view.
Refactor JSON printing for all instances to share more code. This allows Types to act like Instances in Observatory. Update the look and feel for the function-view page. Add script info for functions. Update tests. R=johnmccutchan@google.com Review URL: https://codereview.chromium.org//211283004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@34435 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
6e1d5c293a
commit
99fca31c02
|
@ -289,7 +289,7 @@
|
|||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<span>
|
||||
<template if="{{ isUnexpected(ref.serviceType) }}">
|
||||
unexpected reference type <{{ ref.serviceType }}>
|
||||
</template>
|
||||
|
@ -309,6 +309,10 @@
|
|||
<a href="{{ url }}">{{ ref['preview'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ (isType(ref.serviceType)) }}">
|
||||
<a href="{{ url }}">{{ ref['user_name'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ isClosure(ref.serviceType) }}">
|
||||
<a href="{{ url }}">
|
||||
<!-- TODO(turnidge): Switch this to fully-qualified function -->
|
||||
|
@ -349,8 +353,7 @@
|
|||
</div>
|
||||
</curly-block>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</polymer-element>
|
||||
|
@ -443,11 +446,12 @@
|
|||
var
|
||||
</template>
|
||||
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
|
||||
<class-ref ref="{{ ref['declared_type'] }}"></class-ref>
|
||||
<instance-ref ref="{{ ref['declared_type'] }}"></instance-ref>
|
||||
</template>
|
||||
<a title="{{ hoverText }}" href="{{ url }}">{{ name }}</a>
|
||||
</div>
|
||||
</template> </polymer-element><polymer-element name="function-ref" extends="service-ref">
|
||||
</template> </polymer-element>
|
||||
<polymer-element name="function-ref" extends="service-ref">
|
||||
<template><!-- These comments are here to allow newlines.
|
||||
--><template if="{{ qualified && !hasParent && hasClass }}"><!--
|
||||
--><class-ref ref="{{ ref['class'] }}"></class-ref>.</template><!--
|
||||
|
@ -801,6 +805,28 @@
|
|||
</polymer-element>
|
||||
<polymer-element name="function-view" extends="observatory-element">
|
||||
<template>
|
||||
<style>
|
||||
.content {
|
||||
padding-left: 10%;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font: 400 18px 'Montserrat', sans-serif;
|
||||
}
|
||||
.memberList {
|
||||
display: table;
|
||||
}
|
||||
.memberItem {
|
||||
display: table-row;
|
||||
}
|
||||
.memberName, .memberValue {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
padding: 3px 0 3px 1em;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
<nav-bar>
|
||||
<top-nav-menu></top-nav-menu>
|
||||
<isolate-nav-menu isolate="{{ function.isolate }}"></isolate-nav-menu>
|
||||
|
@ -815,50 +841,86 @@
|
|||
<nav-refresh callback="{{ refresh }}"></nav-refresh>
|
||||
</nav-bar>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
{{ function['user_name'] }} ({{ function['name'] }})
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
<div class="content">
|
||||
<h1>function {{ qualifiedName }}</h1>
|
||||
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">kind</div>
|
||||
<div class="memberValue">
|
||||
<template if="{{ function['is_static'] }}">static</template>
|
||||
<template if="{{ function['is_const'] }}">const</template>
|
||||
{{ kind }}
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>static</td><td>{{ function['is_static'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Const</td><td>{{ function['is_const'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimizable</td><td>{{ function['is_optimizable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inlinable</td><td>{{ function['is_inlinable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kind</td><td>{{ function['kind'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Usage Count</td><td>{{ function['usage_counter'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimized Call Site Count</td><td>{{ function['optimized_call_site_count'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deoptimizations</td><td>{{ function['deoptimizations'] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<template if="{{ function['parent'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent function</div>
|
||||
<div class="memberValue">
|
||||
<function-ref ref="{{ function['parent'] }}"></function-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['parent'] == null &&
|
||||
function['class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">script</div>
|
||||
<div class="memberValue">
|
||||
<script-ref ref="{{ function['script'] }}">
|
||||
</script-ref>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memberItem"> </div>
|
||||
|
||||
<template if="{{ function['code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['unoptimized_code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">unoptimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
</div>
|
||||
<div class="memberValue">
|
||||
<span title="This count is used to determine when a function will be optimized. It is a combination of call counts and other factors.">
|
||||
(usage count: {{ function['usage_counter'] }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">deoptimizations</div>
|
||||
<div class="memberValue">{{ function['deoptimizations'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimizable</div>
|
||||
<div class="memberValue">{{ function['is_optimizable'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">inlinable</div>
|
||||
<div class="memberValue">{{ function['is_inlinable'] }}</div>
|
||||
</div>
|
||||
<template if="{{ function.name != function.vmName }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">vm name</div>
|
||||
<div class="memberValue">{{ function.vmName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</polymer-element>
|
||||
|
@ -1215,7 +1277,12 @@
|
|||
<template if="{{ instance['error'] == null }}">
|
||||
<div class="content">
|
||||
<!-- TODO(turnidge): Handle null instances. -->
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
<template if="{{ isType(instance.serviceType) }}">
|
||||
<h1>type {{ instance['user_name'] }}</h1>
|
||||
</template>
|
||||
<template if="{{ !isType(instance.serviceType) }}">
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
</template>
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">class</div>
|
||||
|
@ -1234,6 +1301,15 @@
|
|||
<div class="memberName">size</div>
|
||||
<div class="memberValue">{{ instance['size'] | formatSize }}</div>
|
||||
</div>
|
||||
<template if="{{ instance['type_class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">type class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ instance['type_class'] }}">
|
||||
</class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -288,7 +288,7 @@
|
|||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<span>
|
||||
<template if="{{ isUnexpected(ref.serviceType) }}">
|
||||
unexpected reference type <{{ ref.serviceType }}>
|
||||
</template>
|
||||
|
@ -308,6 +308,10 @@
|
|||
<a href="{{ url }}">{{ ref['preview'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ (isType(ref.serviceType)) }}">
|
||||
<a href="{{ url }}">{{ ref['user_name'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ isClosure(ref.serviceType) }}">
|
||||
<a href="{{ url }}">
|
||||
<!-- TODO(turnidge): Switch this to fully-qualified function -->
|
||||
|
@ -348,8 +352,7 @@
|
|||
</div>
|
||||
</curly-block>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
</polymer-element>
|
||||
|
@ -442,11 +445,12 @@
|
|||
var
|
||||
</template>
|
||||
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
|
||||
<class-ref ref="{{ ref['declared_type'] }}"></class-ref>
|
||||
<instance-ref ref="{{ ref['declared_type'] }}"></instance-ref>
|
||||
</template>
|
||||
<a title="{{ hoverText }}" href="{{ url }}">{{ name }}</a>
|
||||
</div>
|
||||
</template> </polymer-element><polymer-element name="function-ref" extends="service-ref">
|
||||
</template> </polymer-element>
|
||||
<polymer-element name="function-ref" extends="service-ref">
|
||||
<template><!-- These comments are here to allow newlines.
|
||||
--><template if="{{ qualified && !hasParent && hasClass }}"><!--
|
||||
--><class-ref ref="{{ ref['class'] }}"></class-ref>.</template><!--
|
||||
|
@ -800,6 +804,28 @@
|
|||
</polymer-element>
|
||||
<polymer-element name="function-view" extends="observatory-element">
|
||||
<template>
|
||||
<style>
|
||||
.content {
|
||||
padding-left: 10%;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font: 400 18px 'Montserrat', sans-serif;
|
||||
}
|
||||
.memberList {
|
||||
display: table;
|
||||
}
|
||||
.memberItem {
|
||||
display: table-row;
|
||||
}
|
||||
.memberName, .memberValue {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
padding: 3px 0 3px 1em;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
<nav-bar>
|
||||
<top-nav-menu></top-nav-menu>
|
||||
<isolate-nav-menu isolate="{{ function.isolate }}"></isolate-nav-menu>
|
||||
|
@ -814,50 +840,86 @@
|
|||
<nav-refresh callback="{{ refresh }}"></nav-refresh>
|
||||
</nav-bar>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
{{ function['user_name'] }} ({{ function['name'] }})
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
<div class="content">
|
||||
<h1>function {{ qualifiedName }}</h1>
|
||||
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">kind</div>
|
||||
<div class="memberValue">
|
||||
<template if="{{ function['is_static'] }}">static</template>
|
||||
<template if="{{ function['is_const'] }}">const</template>
|
||||
{{ kind }}
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>static</td><td>{{ function['is_static'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Const</td><td>{{ function['is_const'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimizable</td><td>{{ function['is_optimizable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inlinable</td><td>{{ function['is_inlinable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kind</td><td>{{ function['kind'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Usage Count</td><td>{{ function['usage_counter'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimized Call Site Count</td><td>{{ function['optimized_call_site_count'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deoptimizations</td><td>{{ function['deoptimizations'] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<template if="{{ function['parent'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent function</div>
|
||||
<div class="memberValue">
|
||||
<function-ref ref="{{ function['parent'] }}"></function-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['parent'] == null &&
|
||||
function['class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">script</div>
|
||||
<div class="memberValue">
|
||||
<script-ref ref="{{ function['script'] }}">
|
||||
</script-ref>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memberItem"> </div>
|
||||
|
||||
<template if="{{ function['code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['unoptimized_code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">unoptimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
</div>
|
||||
<div class="memberValue">
|
||||
<span title="This count is used to determine when a function will be optimized. It is a combination of call counts and other factors.">
|
||||
(usage count: {{ function['usage_counter'] }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">deoptimizations</div>
|
||||
<div class="memberValue">{{ function['deoptimizations'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimizable</div>
|
||||
<div class="memberValue">{{ function['is_optimizable'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">inlinable</div>
|
||||
<div class="memberValue">{{ function['is_inlinable'] }}</div>
|
||||
</div>
|
||||
<template if="{{ function.name != function.vmName }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">vm name</div>
|
||||
<div class="memberValue">{{ function.vmName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</polymer-element>
|
||||
|
@ -1214,7 +1276,12 @@
|
|||
<template if="{{ instance['error'] == null }}">
|
||||
<div class="content">
|
||||
<!-- TODO(turnidge): Handle null instances. -->
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
<template if="{{ isType(instance.serviceType) }}">
|
||||
<h1>type {{ instance['user_name'] }}</h1>
|
||||
</template>
|
||||
<template if="{{ !isType(instance.serviceType) }}">
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
</template>
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">class</div>
|
||||
|
@ -1233,6 +1300,15 @@
|
|||
<div class="memberName">size</div>
|
||||
<div class="memberValue">{{ instance['size'] | formatSize }}</div>
|
||||
</div>
|
||||
<template if="{{ instance['type_class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">type class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ instance['type_class'] }}">
|
||||
</class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,5 @@
|
|||
<head>
|
||||
<link rel="import" href="class_ref.html">
|
||||
<link rel="import" href="instance_ref.html">
|
||||
<link rel="import" href="observatory_element.html">
|
||||
<link rel="import" href="service_ref.html">
|
||||
</head>
|
||||
|
@ -12,8 +12,8 @@
|
|||
var
|
||||
</template>
|
||||
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
|
||||
<class-ref ref="{{ ref['declared_type'] }}"></class-ref>
|
||||
<instance-ref ref="{{ ref['declared_type'] }}"></instance-ref>
|
||||
</template>
|
||||
<a title="{{ hoverText }}" href="{{ url }}">{{ name }}</a>
|
||||
</div>
|
||||
</template> <script type="application/dart" src="field_ref.dart"></script> </polymer-element>
|
||||
</template> <script type="application/dart" src="field_ref.dart"></script> </polymer-element>
|
||||
|
|
|
@ -1,11 +1,35 @@
|
|||
<head>
|
||||
<link rel="import" href="class_ref.html">
|
||||
<link rel="import" href="code_ref.html">
|
||||
<link rel="import" href="function_ref.html">
|
||||
<link rel="import" href="observatory_element.html">
|
||||
<link rel="import" href="nav_bar.html">
|
||||
<link rel="import" href="script_ref.html">
|
||||
</head>
|
||||
<polymer-element name="function-view" extends="observatory-element">
|
||||
<template>
|
||||
<style>
|
||||
.content {
|
||||
padding-left: 10%;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font: 400 18px 'Montserrat', sans-serif;
|
||||
}
|
||||
.memberList {
|
||||
display: table;
|
||||
}
|
||||
.memberItem {
|
||||
display: table-row;
|
||||
}
|
||||
.memberName, .memberValue {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
padding: 3px 0 3px 1em;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
<nav-bar>
|
||||
<top-nav-menu></top-nav-menu>
|
||||
<isolate-nav-menu isolate="{{ function.isolate }}"></isolate-nav-menu>
|
||||
|
@ -20,50 +44,86 @@
|
|||
<nav-refresh callback="{{ refresh }}"></nav-refresh>
|
||||
</nav-bar>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
{{ function['user_name'] }} ({{ function['name'] }})
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
<div class="content">
|
||||
<h1>function {{ qualifiedName }}</h1>
|
||||
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">kind</div>
|
||||
<div class="memberValue">
|
||||
<template if="{{ function['is_static'] }}">static</template>
|
||||
<template if="{{ function['is_const'] }}">const</template>
|
||||
{{ kind }}
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>static</td><td>{{ function['is_static'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Const</td><td>{{ function['is_const'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimizable</td><td>{{ function['is_optimizable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inlinable</td><td>{{ function['is_inlinable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kind</td><td>{{ function['kind'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Usage Count</td><td>{{ function['usage_counter'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimized Call Site Count</td><td>{{ function['optimized_call_site_count'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deoptimizations</td><td>{{ function['deoptimizations'] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<template if="{{ function['parent'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent function</div>
|
||||
<div class="memberValue">
|
||||
<function-ref ref="{{ function['parent'] }}"></function-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['parent'] == null &&
|
||||
function['class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">script</div>
|
||||
<div class="memberValue">
|
||||
<script-ref ref="{{ function['script'] }}">
|
||||
</script-ref>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memberItem"> </div>
|
||||
|
||||
<template if="{{ function['code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['unoptimized_code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">unoptimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
</div>
|
||||
<div class="memberValue">
|
||||
<span title="This count is used to determine when a function will be optimized. It is a combination of call counts and other factors.">
|
||||
(usage count: {{ function['usage_counter'] }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">deoptimizations</div>
|
||||
<div class="memberValue">{{ function['deoptimizations'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimizable</div>
|
||||
<div class="memberValue">{{ function['is_optimizable'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">inlinable</div>
|
||||
<div class="memberValue">{{ function['is_inlinable'] }}</div>
|
||||
</div>
|
||||
<template if="{{ function.name != function.vmName }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">vm name</div>
|
||||
<div class="memberValue">{{ function.vmName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="application/dart" src="function_view.dart"></script>
|
||||
</polymer-element>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<span>
|
||||
<template if="{{ isUnexpected(ref.serviceType) }}">
|
||||
unexpected reference type <{{ ref.serviceType }}>
|
||||
</template>
|
||||
|
@ -39,6 +39,10 @@
|
|||
<a href="{{ url }}">{{ ref['preview'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ (isType(ref.serviceType)) }}">
|
||||
<a href="{{ url }}">{{ ref['user_name'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ isClosure(ref.serviceType) }}">
|
||||
<a href="{{ url }}">
|
||||
<!-- TODO(turnidge): Switch this to fully-qualified function -->
|
||||
|
@ -79,8 +83,7 @@
|
|||
</div>
|
||||
</curly-block>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
<script type="application/dart" src="instance_ref.dart"></script>
|
||||
</polymer-element>
|
||||
|
|
|
@ -47,7 +47,12 @@
|
|||
<template if="{{ instance['error'] == null }}">
|
||||
<div class="content">
|
||||
<!-- TODO(turnidge): Handle null instances. -->
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
<template if="{{ isType(instance.serviceType) }}">
|
||||
<h1>type {{ instance['user_name'] }}</h1>
|
||||
</template>
|
||||
<template if="{{ !isType(instance.serviceType) }}">
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
</template>
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">class</div>
|
||||
|
@ -66,6 +71,15 @@
|
|||
<div class="memberName">size</div>
|
||||
<div class="memberValue">{{ instance['size'] | formatSize }}</div>
|
||||
</div>
|
||||
<template if="{{ instance['type_class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">type class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ instance['type_class'] }}">
|
||||
</class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<head>
|
||||
<link rel="import" href="class_ref.html">
|
||||
<link rel="import" href="instance_ref.html">
|
||||
<link rel="import" href="observatory_element.html">
|
||||
<link rel="import" href="service_ref.html">
|
||||
</head>
|
||||
|
@ -12,8 +12,8 @@
|
|||
var
|
||||
</template>
|
||||
<template if="{{ (ref['declared_type']['name'] != 'dynamic') }}">
|
||||
<class-ref ref="{{ ref['declared_type'] }}"></class-ref>
|
||||
<instance-ref ref="{{ ref['declared_type'] }}"></instance-ref>
|
||||
</template>
|
||||
<a title="{{ hoverText }}" href="{{ url }}">{{ name }}</a>
|
||||
</div>
|
||||
</template> <script type="application/dart" src="field_ref.dart"></script> </polymer-element>
|
||||
</template> <script type="application/dart" src="field_ref.dart"></script> </polymer-element>
|
||||
|
|
|
@ -14,7 +14,76 @@ class FunctionViewElement extends ObservatoryElement {
|
|||
@published ServiceMap function;
|
||||
FunctionViewElement.created() : super.created();
|
||||
|
||||
// TODO(turnidge): Once we create a Function object, these fields
|
||||
// should move there.
|
||||
@published String qualifiedName;
|
||||
@published String kind;
|
||||
|
||||
String _getQualifiedName(ServiceMap function) {
|
||||
var parent = (function != null && function['parent'] != null
|
||||
? function['parent'] : null);
|
||||
if (parent != null) {
|
||||
return "${_getQualifiedName(parent)}.${function['user_name']}";
|
||||
}
|
||||
var cls = (function != null &&
|
||||
function['class'] != null &&
|
||||
function['class']['user_name'] != null &&
|
||||
function['class']['user_name'] != '::'
|
||||
? function['class'] : null);
|
||||
if (cls != null) {
|
||||
return "${cls['user_name']}.${function['user_name']}";
|
||||
}
|
||||
return "${function['username']}";
|
||||
}
|
||||
|
||||
void functionChanged(oldValue) {
|
||||
notifyPropertyChange(#qualifiedName, 0, 1);
|
||||
notifyPropertyChange(#kind, 0, 1);
|
||||
qualifiedName = _getQualifiedName(function);
|
||||
switch(function['kind']) {
|
||||
case 'kRegularFunction':
|
||||
kind = 'function';
|
||||
break;
|
||||
case 'kClosureFunction':
|
||||
kind = 'closure function';
|
||||
break;
|
||||
case 'kSignatureFunction':
|
||||
kind = 'signature function';
|
||||
break;
|
||||
case 'kGetterFunction':
|
||||
kind = 'getter function';
|
||||
break;
|
||||
case 'kSetterFunction':
|
||||
kind = 'setter function';
|
||||
break;
|
||||
case 'kConstructor':
|
||||
kind = 'constructor';
|
||||
break;
|
||||
case 'kImplicitGetterFunction':
|
||||
kind = 'implicit getter function';
|
||||
break;
|
||||
case 'kImplicitSetterFunction':
|
||||
kind = 'implicit setter function';
|
||||
break;
|
||||
case 'kStaticInitializer':
|
||||
kind = 'static initializer';
|
||||
break;
|
||||
case 'kMethodExtractor':
|
||||
kind = 'method extractor';
|
||||
break;
|
||||
case 'kNoSuchMethodDispatcher':
|
||||
kind = 'noSuchMethod dispatcher';
|
||||
break;
|
||||
case 'kInvokeFieldDispatcher':
|
||||
kind = 'invoke field dispatcher';
|
||||
break;
|
||||
default:
|
||||
kind = 'UNKNOWN';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void refresh(var done) {
|
||||
function.reload().whenComplete(done);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,35 @@
|
|||
<head>
|
||||
<link rel="import" href="class_ref.html">
|
||||
<link rel="import" href="code_ref.html">
|
||||
<link rel="import" href="function_ref.html">
|
||||
<link rel="import" href="observatory_element.html">
|
||||
<link rel="import" href="nav_bar.html">
|
||||
<link rel="import" href="script_ref.html">
|
||||
</head>
|
||||
<polymer-element name="function-view" extends="observatory-element">
|
||||
<template>
|
||||
<style>
|
||||
.content {
|
||||
padding-left: 10%;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font: 400 18px 'Montserrat', sans-serif;
|
||||
}
|
||||
.memberList {
|
||||
display: table;
|
||||
}
|
||||
.memberItem {
|
||||
display: table-row;
|
||||
}
|
||||
.memberName, .memberValue {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
padding: 3px 0 3px 1em;
|
||||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
|
||||
<nav-bar>
|
||||
<top-nav-menu></top-nav-menu>
|
||||
<isolate-nav-menu isolate="{{ function.isolate }}"></isolate-nav-menu>
|
||||
|
@ -20,50 +44,86 @@
|
|||
<nav-refresh callback="{{ refresh }}"></nav-refresh>
|
||||
</nav-bar>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
{{ function['user_name'] }} ({{ function['name'] }})
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div>
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
<div class="content">
|
||||
<h1>function {{ qualifiedName }}</h1>
|
||||
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">kind</div>
|
||||
<div class="memberValue">
|
||||
<template if="{{ function['is_static'] }}">static</template>
|
||||
<template if="{{ function['is_const'] }}">const</template>
|
||||
{{ kind }}
|
||||
</div>
|
||||
<table class="table table-hover">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>static</td><td>{{ function['is_static'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Const</td><td>{{ function['is_const'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimizable</td><td>{{ function['is_optimizable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inlinable</td><td>{{ function['is_inlinable'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Kind</td><td>{{ function['kind'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Usage Count</td><td>{{ function['usage_counter'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Optimized Call Site Count</td><td>{{ function['optimized_call_site_count'] }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Deoptimizations</td><td>{{ function['deoptimizations'] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<template if="{{ function['parent'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent function</div>
|
||||
<div class="memberValue">
|
||||
<function-ref ref="{{ function['parent'] }}"></function-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['parent'] == null &&
|
||||
function['class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">parent class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ function['class'] }}"></class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">script</div>
|
||||
<div class="memberValue">
|
||||
<script-ref ref="{{ function['script'] }}">
|
||||
</script-ref>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="memberItem"> </div>
|
||||
|
||||
<template if="{{ function['code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['code'] }}"></code-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template if="{{ function['unoptimized_code'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">unoptimized code</div>
|
||||
<div class="memberValue">
|
||||
<code-ref ref="{{ function['unoptimized_code'] }}"></code-ref>
|
||||
</div>
|
||||
<div class="memberValue">
|
||||
<span title="This count is used to determine when a function will be optimized. It is a combination of call counts and other factors.">
|
||||
(usage count: {{ function['usage_counter'] }})
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">deoptimizations</div>
|
||||
<div class="memberValue">{{ function['deoptimizations'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">optimizable</div>
|
||||
<div class="memberValue">{{ function['is_optimizable'] }}</div>
|
||||
</div>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">inlinable</div>
|
||||
<div class="memberValue">{{ function['is_inlinable'] }}</div>
|
||||
</div>
|
||||
<template if="{{ function.name != function.vmName }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">vm name</div>
|
||||
<div class="memberValue">{{ function.vmName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script type="application/dart" src="function_view.dart"></script>
|
||||
</polymer-element>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
font: 400 14px 'Montserrat', sans-serif;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<span>
|
||||
<template if="{{ isUnexpected(ref.serviceType) }}">
|
||||
unexpected reference type <{{ ref.serviceType }}>
|
||||
</template>
|
||||
|
@ -39,6 +39,10 @@
|
|||
<a href="{{ url }}">{{ ref['preview'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ (isType(ref.serviceType)) }}">
|
||||
<a href="{{ url }}">{{ ref['user_name'] }}</a>
|
||||
</template>
|
||||
|
||||
<template if="{{ isClosure(ref.serviceType) }}">
|
||||
<a href="{{ url }}">
|
||||
<!-- TODO(turnidge): Switch this to fully-qualified function -->
|
||||
|
@ -79,8 +83,7 @@
|
|||
</div>
|
||||
</curly-block>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</span>
|
||||
</template>
|
||||
<script type="application/dart" src="instance_ref.dart"></script>
|
||||
</polymer-element>
|
||||
|
|
|
@ -47,7 +47,12 @@
|
|||
<template if="{{ instance['error'] == null }}">
|
||||
<div class="content">
|
||||
<!-- TODO(turnidge): Handle null instances. -->
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
<template if="{{ isType(instance.serviceType) }}">
|
||||
<h1>type {{ instance['user_name'] }}</h1>
|
||||
</template>
|
||||
<template if="{{ !isType(instance.serviceType) }}">
|
||||
<h1>instance of {{ instance['class']['user_name'] }}</h1>
|
||||
</template>
|
||||
<div class="memberList">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">class</div>
|
||||
|
@ -66,6 +71,15 @@
|
|||
<div class="memberName">size</div>
|
||||
<div class="memberValue">{{ instance['size'] | formatSize }}</div>
|
||||
</div>
|
||||
<template if="{{ instance['type_class'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">type class</div>
|
||||
<div class="memberValue">
|
||||
<class-ref ref="{{ instance['type_class'] }}">
|
||||
</class-ref>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -161,6 +161,10 @@ class ObservatoryElement extends PolymerElement {
|
|||
type == 'Array');
|
||||
}
|
||||
|
||||
bool isType(String type) {
|
||||
return (type == 'Type');
|
||||
}
|
||||
|
||||
bool isUnexpected(String type) {
|
||||
return (!['Null',
|
||||
'Smi',
|
||||
|
@ -173,6 +177,7 @@ class ObservatoryElement extends PolymerElement {
|
|||
'Instance',
|
||||
'GrowableObjectArray',
|
||||
'Array',
|
||||
'Type',
|
||||
'Error'].contains(type));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ class ServiceObjectViewElement extends ObservatoryElement {
|
|||
case 'Instance':
|
||||
case 'Smi':
|
||||
case 'String':
|
||||
case 'Type':
|
||||
InstanceViewElement element = new Element.tag('instance-view');
|
||||
element.instance = object;
|
||||
return element;
|
||||
|
|
|
@ -899,6 +899,8 @@ void Isolate::PrintToJSONStream(JSONStream* stream, bool ref) {
|
|||
jsheap.AddProperty("capacityOld", heap()->CapacityInWords(Heap::kOld));
|
||||
}
|
||||
|
||||
// TODO(turnidge): Don't compute a full stack trace every time we
|
||||
// request an isolate's info.
|
||||
DebuggerStackTrace* stack = debugger()->StackTrace();
|
||||
if (stack->Length() > 0) {
|
||||
JSONObject jsframe(&jsobj, "topFrame");
|
||||
|
|
|
@ -6365,6 +6365,13 @@ void Function::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
|||
jsobj.AddProperty("code", Object::Handle(CurrentCode()));
|
||||
jsobj.AddProperty("deoptimizations",
|
||||
static_cast<intptr_t>(deoptimization_counter()));
|
||||
|
||||
const Script& script = Script::Handle(this->script());
|
||||
if (!script.IsNull()) {
|
||||
jsobj.AddProperty("script", script);
|
||||
jsobj.AddProperty("token_pos", token_pos());
|
||||
jsobj.AddProperty("end_token_pos", end_token_pos());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6663,14 +6670,8 @@ void Field::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
|||
|
||||
jsobj.AddProperty("owner", cls);
|
||||
|
||||
// TODO(turnidge): Once the vmservice supports returning types,
|
||||
// return the type here instead of the class.
|
||||
AbstractType& declared_type = AbstractType::Handle(type());
|
||||
if (declared_type.HasResolvedTypeClass()) {
|
||||
cls = declared_type.type_class();
|
||||
jsobj.AddProperty("declared_type", cls);
|
||||
}
|
||||
|
||||
jsobj.AddProperty("declared_type", declared_type);
|
||||
jsobj.AddProperty("static", is_static());
|
||||
jsobj.AddProperty("final", is_final());
|
||||
jsobj.AddProperty("const", is_const());
|
||||
|
@ -12472,11 +12473,54 @@ const char* Instance::ToUserCString(intptr_t max_len, intptr_t nesting) const {
|
|||
}
|
||||
|
||||
|
||||
void Instance::PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const {
|
||||
jsobj->AddProperty("type", JSONType(ref));
|
||||
Class& cls = Class::Handle(this->clazz());
|
||||
jsobj->AddProperty("class", cls);
|
||||
if (ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
jsobj->AddProperty("size", raw()->Size());
|
||||
|
||||
// Walk the superclass chain, adding all instance fields.
|
||||
{
|
||||
Instance& fieldValue = Instance::Handle();
|
||||
JSONArray jsarr(jsobj, "fields");
|
||||
while (!cls.IsNull()) {
|
||||
const Array& field_array = Array::Handle(cls.fields());
|
||||
Field& field = Field::Handle();
|
||||
if (!field_array.IsNull()) {
|
||||
for (intptr_t i = 0; i < field_array.Length(); i++) {
|
||||
field ^= field_array.At(i);
|
||||
if (!field.is_static()) {
|
||||
fieldValue ^= GetField(field);
|
||||
JSONObject jsfield(&jsarr);
|
||||
jsfield.AddProperty("decl", field);
|
||||
jsfield.AddProperty("value", fieldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
cls = cls.SuperClass();
|
||||
}
|
||||
}
|
||||
|
||||
if (NumNativeFields() > 0) {
|
||||
JSONArray jsarr(jsobj, "nativeFields");
|
||||
for (intptr_t i = 0; i < NumNativeFields(); i++) {
|
||||
intptr_t value = GetNativeField(i);
|
||||
JSONObject jsfield(&jsarr);
|
||||
jsfield.AddProperty("index", i);
|
||||
jsfield.AddProperty("value", value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Instance::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
Class& cls = Class::Handle(this->clazz());
|
||||
|
||||
// TODO(turnidge): Handle <optimized out> like other null-like values.
|
||||
// Handle certain special instance values.
|
||||
if (IsNull()) {
|
||||
jsobj.AddProperty("type", ref ? "@Null" : "Null");
|
||||
jsobj.AddProperty("id", "objects/null");
|
||||
|
@ -12500,57 +12544,20 @@ void Instance::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
|||
jsobj.AddProperty("id", "objects/optimized-out");
|
||||
jsobj.AddProperty("preview", "<optimized out>");
|
||||
return;
|
||||
} else {
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
if (IsClosure()) {
|
||||
const Function& closureFunc = Function::Handle(Closure::function(*this));
|
||||
jsobj.AddProperty("closureFunc", closureFunc);
|
||||
jsobj.AddProperty("type", ref ? "@Closure" : "Closure");
|
||||
} else {
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
}
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
jsobj.AddProperty("class", cls);
|
||||
jsobj.AddProperty("preview", ToUserCString(40));
|
||||
}
|
||||
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
if (IsClosure()) {
|
||||
const Function& closureFunc = Function::Handle(Closure::function(*this));
|
||||
jsobj.AddProperty("closureFunc", closureFunc);
|
||||
}
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
jsobj.AddProperty("preview", ToUserCString(40));
|
||||
if (ref) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk the superclass chain, adding all instance fields.
|
||||
{
|
||||
Instance& fieldValue = Instance::Handle();
|
||||
JSONArray jsarr(&jsobj, "fields");
|
||||
while (!cls.IsNull()) {
|
||||
const Array& field_array = Array::Handle(cls.fields());
|
||||
Field& field = Field::Handle();
|
||||
if (!field_array.IsNull()) {
|
||||
for (intptr_t i = 0; i < field_array.Length(); i++) {
|
||||
field ^= field_array.At(i);
|
||||
if (!field.is_static()) {
|
||||
fieldValue ^= GetField(field);
|
||||
JSONObject jsfield(&jsarr);
|
||||
jsfield.AddProperty("decl", field);
|
||||
jsfield.AddProperty("value", fieldValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
cls = cls.SuperClass();
|
||||
}
|
||||
}
|
||||
|
||||
if (NumNativeFields() > 0) {
|
||||
JSONArray jsarr(&jsobj, "nativeFields");
|
||||
for (intptr_t i = 0; i < NumNativeFields(); i++) {
|
||||
intptr_t value = GetNativeField(i);
|
||||
JSONObject jsfield(&jsarr);
|
||||
jsfield.AddProperty("index", i);
|
||||
jsfield.AddProperty("value", value);
|
||||
}
|
||||
}
|
||||
|
||||
jsobj.AddProperty("size", raw()->Size());
|
||||
}
|
||||
|
||||
|
||||
|
@ -13493,18 +13500,20 @@ const char* Type::ToCString() const {
|
|||
|
||||
|
||||
void Type::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
||||
// TODO(koda): Decide whether to assign stable ids to non-canonical types.
|
||||
if (!IsCanonical()) {
|
||||
return Object::PrintToJSONStream(stream, ref);
|
||||
}
|
||||
ASSERT(IsCanonical());
|
||||
JSONObject jsobj(stream);
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
const Class& type_cls = Class::Handle(type_class());
|
||||
intptr_t id = type_cls.FindCanonicalTypeIndex(*this);
|
||||
ASSERT(id >= 0);
|
||||
intptr_t cid = type_cls.id();
|
||||
jsobj.AddPropertyF("id", "classes/%" Pd "/types/%" Pd "", cid, id);
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
if (IsCanonical()) {
|
||||
const Class& type_cls = Class::Handle(type_class());
|
||||
intptr_t id = type_cls.FindCanonicalTypeIndex(*this);
|
||||
ASSERT(id >= 0);
|
||||
intptr_t cid = type_cls.id();
|
||||
jsobj.AddPropertyF("id", "classes/%" Pd "/types/%" Pd "", cid, id);
|
||||
jsobj.AddProperty("type_class", type_cls);
|
||||
} else {
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
}
|
||||
const char* name = String::Handle(Name()).ToCString();
|
||||
const char* user_name = String::Handle(UserVisibleName()).ToCString();
|
||||
jsobj.AddProperty("name", name);
|
||||
|
@ -13512,7 +13521,6 @@ void Type::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
|||
if (ref) {
|
||||
return;
|
||||
}
|
||||
jsobj.AddProperty("type_class", type_cls);
|
||||
jsobj.AddProperty("type_arguments", TypeArguments::Handle(arguments()));
|
||||
}
|
||||
|
||||
|
@ -13682,9 +13690,9 @@ const char* TypeRef::ToCString() const {
|
|||
|
||||
void TypeRef::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
const char* name = String::Handle(Name()).ToCString();
|
||||
const char* user_name = String::Handle(UserVisibleName()).ToCString();
|
||||
|
@ -13898,16 +13906,16 @@ const char* TypeParameter::ToCString() const {
|
|||
|
||||
void TypeParameter::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
const char* name = String::Handle(Name()).ToCString();
|
||||
const char* user_name = String::Handle(UserVisibleName()).ToCString();
|
||||
jsobj.AddProperty("name", name);
|
||||
jsobj.AddProperty("user_name", user_name);
|
||||
const Class& cls = Class::Handle(parameterized_class());
|
||||
jsobj.AddProperty("parameterized_class", cls);
|
||||
const Class& param_cls = Class::Handle(parameterized_class());
|
||||
jsobj.AddProperty("parameterized_class", param_cls);
|
||||
if (ref) {
|
||||
return;
|
||||
}
|
||||
|
@ -14095,9 +14103,9 @@ const char* BoundedType::ToCString() const {
|
|||
|
||||
void BoundedType::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
const char* name = String::Handle(Name()).ToCString();
|
||||
const char* user_name = String::Handle(UserVisibleName()).ToCString();
|
||||
|
@ -16788,12 +16796,10 @@ const char* Array::ToCString() const {
|
|||
|
||||
void Array::PrintToJSONStream(JSONStream* stream, bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
Class& cls = Class::Handle(this->clazz());
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
jsobj.AddProperty("class", cls);
|
||||
jsobj.AddProperty("length", Length());
|
||||
if (ref) {
|
||||
return;
|
||||
|
@ -17127,12 +17133,10 @@ const char* GrowableObjectArray::ToUserCString(intptr_t max_len,
|
|||
void GrowableObjectArray::PrintToJSONStream(JSONStream* stream,
|
||||
bool ref) const {
|
||||
JSONObject jsobj(stream);
|
||||
Class& cls = Class::Handle(this->clazz());
|
||||
PrintSharedInstanceJSON(&jsobj, ref);
|
||||
ObjectIdRing* ring = Isolate::Current()->object_id_ring();
|
||||
const intptr_t id = ring->GetIdForObject(raw());
|
||||
jsobj.AddProperty("type", JSONType(ref));
|
||||
jsobj.AddPropertyF("id", "objects/%" Pd "", id);
|
||||
jsobj.AddProperty("class", cls);
|
||||
jsobj.AddProperty("length", Length());
|
||||
if (ref) {
|
||||
return;
|
||||
|
|
|
@ -4075,6 +4075,9 @@ class Instance : public Object {
|
|||
|
||||
static RawInstance* New(const Class& cls, Heap::Space space = Heap::kNew);
|
||||
|
||||
protected:
|
||||
virtual void PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const;
|
||||
|
||||
private:
|
||||
RawObject** FieldAddrAtOffset(intptr_t offset) const {
|
||||
ASSERT(IsValidFieldOffset(offset));
|
||||
|
|
|
@ -798,6 +798,54 @@ static bool GetCodeId(const char* s, int64_t* timestamp, uword* address) {
|
|||
}
|
||||
|
||||
|
||||
static bool HandleInstanceCommands(Isolate* isolate,
|
||||
const Object& obj,
|
||||
JSONStream* js,
|
||||
intptr_t arg_pos) {
|
||||
ASSERT(js->num_arguments() > arg_pos);
|
||||
const char* action = js->GetArgument(arg_pos);
|
||||
if (strcmp(action, "eval") == 0) {
|
||||
if (js->num_arguments() > (arg_pos + 1)) {
|
||||
PrintError(js, "expected at most %" Pd " arguments but found %" Pd "\n",
|
||||
arg_pos + 1,
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
if (obj.IsNull()) {
|
||||
PrintErrorWithKind(js, "EvalCollected",
|
||||
"attempt to evaluate against collected object\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
if (obj.raw() == Object::sentinel().raw()) {
|
||||
PrintErrorWithKind(js, "EvalExpired",
|
||||
"attempt to evaluate against expired object\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
const char* expr = js->LookupOption("expr");
|
||||
if (expr == NULL) {
|
||||
PrintError(js, "eval expects an 'expr' option\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
const String& expr_str = String::Handle(isolate, String::New(expr));
|
||||
ASSERT(obj.IsInstance());
|
||||
const Instance& instance = Instance::Cast(obj);
|
||||
const Object& result = Object::Handle(instance.Evaluate(expr_str));
|
||||
if (result.IsNull()) {
|
||||
Object::null_instance().PrintToJSONStream(js, true);
|
||||
} else {
|
||||
result.PrintToJSONStream(js, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PrintError(js, "unrecognized action '%s'\n", action);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool HandleClassesClosures(Isolate* isolate, const Class& cls,
|
||||
JSONStream* js) {
|
||||
intptr_t id;
|
||||
|
@ -944,11 +992,8 @@ static bool HandleClassesTypes(Isolate* isolate, const Class& cls,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
ASSERT(js->num_arguments() >= 4);
|
||||
intptr_t id;
|
||||
if (js->num_arguments() > 4) {
|
||||
PrintError(js, "Command too long");
|
||||
return true;
|
||||
}
|
||||
if (!GetIntegerId(js->GetArgument(3), &id)) {
|
||||
PrintError(js, "Must specify collection object id: types/id");
|
||||
return true;
|
||||
|
@ -959,8 +1004,11 @@ static bool HandleClassesTypes(Isolate* isolate, const Class& cls,
|
|||
PrintError(js, "Canonical type %" Pd " not found", id);
|
||||
return true;
|
||||
}
|
||||
type.PrintToJSONStream(js, false);
|
||||
return true;
|
||||
if (js->num_arguments() == 4) {
|
||||
type.PrintToJSONStream(js, false);
|
||||
return true;
|
||||
}
|
||||
return HandleInstanceCommands(isolate, type, js, 4);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1181,8 +1229,6 @@ static bool HandleObjects(Isolate* isolate, JSONStream* js) {
|
|||
PrintError(js, "unrecognized object id '%s'", arg);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now what should we do with the object?
|
||||
if (js->num_arguments() == 2) {
|
||||
// Print.
|
||||
if (obj.IsNull()) {
|
||||
|
@ -1197,47 +1243,7 @@ static bool HandleObjects(Isolate* isolate, JSONStream* js) {
|
|||
obj.PrintToJSONStream(js, false);
|
||||
return true;
|
||||
}
|
||||
ASSERT(js->num_arguments() > 2);
|
||||
|
||||
const char* action = js->GetArgument(2);
|
||||
if (strcmp(action, "eval") == 0) {
|
||||
if (js->num_arguments() > 3) {
|
||||
PrintError(js, "expected at most 3 arguments but found %" Pd "\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
if (obj.IsNull()) {
|
||||
PrintErrorWithKind(js, "EvalCollected",
|
||||
"attempt to evaluate against collected object\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
if (obj.raw() == Object::sentinel().raw()) {
|
||||
PrintErrorWithKind(js, "EvalExpired",
|
||||
"attempt to evaluate against expired object\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
const char* expr = js->LookupOption("expr");
|
||||
if (expr == NULL) {
|
||||
PrintError(js, "eval expects an 'expr' option\n",
|
||||
js->num_arguments());
|
||||
return true;
|
||||
}
|
||||
const String& expr_str = String::Handle(isolate, String::New(expr));
|
||||
ASSERT(obj.IsInstance());
|
||||
const Instance& instance = Instance::Cast(obj);
|
||||
const Object& result = Object::Handle(instance.Evaluate(expr_str));
|
||||
if (result.IsNull()) {
|
||||
Object::null_instance().PrintToJSONStream(js, true);
|
||||
} else {
|
||||
result.PrintToJSONStream(js, true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PrintError(js, "unrecognized action '%s'\n", action);
|
||||
return true;
|
||||
return HandleInstanceCommands(isolate, obj, js, 2);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -112,6 +112,9 @@ static RawInstance* EvalF(Dart_Handle lib, const char* fmt, ...) {
|
|||
|
||||
|
||||
// Search for the formatted string in buff.
|
||||
//
|
||||
// TODO(turnidge): This function obscures the line number of failing
|
||||
// EXPECTs. Rework this.
|
||||
static void ExpectSubstringF(const char* buff, const char* fmt, ...) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
|
||||
|
@ -456,10 +459,10 @@ TEST_CASE(Service_Objects) {
|
|||
handler.filterMsg("name");
|
||||
handler.filterMsg("size");
|
||||
EXPECT_STREQ(
|
||||
"{\"type\":\"String\",\"id\":\"objects\\/1\","
|
||||
"{\"type\":\"String\","
|
||||
"\"class\":{\"type\":\"@Class\",\"id\":\"classes\\/60\","
|
||||
"\"user_name\":\"String\"},\"preview\":\"\\\"value\\\"\","
|
||||
"\"fields\":[],}",
|
||||
"\"user_name\":\"String\"},\"fields\":[],"
|
||||
"\"id\":\"objects\\/1\",\"preview\":\"\\\"value\\\"\"}",
|
||||
handler.msg());
|
||||
|
||||
// object id ring / invalid => expired
|
||||
|
@ -781,8 +784,9 @@ TEST_CASE(Service_Types) {
|
|||
Service::HandleIsolateMessage(isolate, service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING("\"type\":\"Class\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"name\":\"A\"", handler.msg());
|
||||
ExpectSubstringF(handler.msg(),
|
||||
"\"id\":\"classes\\/%" Pd "\",\"name\":\"A\",", cid);
|
||||
"\"id\":\"classes\\/%" Pd "\"", cid);
|
||||
|
||||
// Request canonical type 0 from class A.
|
||||
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'types', '0'],"
|
||||
|
@ -790,9 +794,9 @@ TEST_CASE(Service_Types) {
|
|||
Service::HandleIsolateMessage(isolate, service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING("\"type\":\"Type\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"name\":\"A<bool>\"", handler.msg());
|
||||
ExpectSubstringF(handler.msg(),
|
||||
"\"id\":\"classes\\/%" Pd "\\/types\\/0\","
|
||||
"\"name\":\"A<bool>\",", cid);
|
||||
"\"id\":\"classes\\/%" Pd "\\/types\\/0\"", cid);
|
||||
|
||||
// Request canonical type 1 from class A.
|
||||
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'types', '1'],"
|
||||
|
@ -800,9 +804,9 @@ TEST_CASE(Service_Types) {
|
|||
Service::HandleIsolateMessage(isolate, service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING("\"type\":\"Type\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"name\":\"A<A<bool>>\"", handler.msg());
|
||||
ExpectSubstringF(handler.msg(),
|
||||
"\"id\":\"classes\\/%" Pd "\\/types\\/1\","
|
||||
"\"name\":\"A<A<bool>>\",", cid);
|
||||
"\"id\":\"classes\\/%" Pd "\\/types\\/1\"", cid);
|
||||
|
||||
// Request for non-existent canonical type from class A.
|
||||
service_msg = EvalF(h_lib, "[port, ['classes', '%" Pd "', 'types', '42'],"
|
||||
|
|
Loading…
Reference in a new issue