mirror of
https://github.com/dart-lang/sdk
synced 2024-09-19 14:43:32 +00:00
Show flags in Observatory.
Add vm support for setting flags through vm service (UI coming soon). e.g. http://127.0.0.1:8181/#/flags/set?name=some_flag&value=100 -- I reworked the Flags class to use a growing array rather than a linked list to store flags. This means that we don't need to go through the hassle of building an array and sorting every time that we print/printjson. R=johnmccutchan@google.com Review URL: https://codereview.chromium.org//299143007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@36712 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
2b06c73841
commit
8db11b79ac
File diff suppressed because it is too large
Load diff
|
@ -1 +1 @@
|
|||
{"experimental_bootstrap":false,"script_ids":[["observatory","lib/src/elements/curly_block.dart"],["observatory","lib/src/elements/observatory_element.dart"],["observatory","lib/src/elements/service_ref.dart"],["observatory","lib/src/elements/instance_ref.dart"],["observatory","lib/src/elements/action_link.dart"],["observatory","lib/src/elements/nav_bar.dart"],["observatory","lib/src/elements/breakpoint_list.dart"],["observatory","lib/src/elements/class_ref.dart"],["observatory","lib/src/elements/eval_box.dart"],["observatory","lib/src/elements/eval_link.dart"],["observatory","lib/src/elements/field_ref.dart"],["observatory","lib/src/elements/function_ref.dart"],["observatory","lib/src/elements/library_ref.dart"],["observatory","lib/src/elements/script_ref.dart"],["observatory","lib/src/elements/class_view.dart"],["observatory","lib/src/elements/code_ref.dart"],["observatory","lib/src/elements/code_view.dart"],["observatory","lib/src/elements/collapsible_content.dart"],["observatory","lib/src/elements/error_view.dart"],["observatory","lib/src/elements/field_view.dart"],["observatory","lib/src/elements/script_inset.dart"],["observatory","lib/src/elements/function_view.dart"],["observatory","lib/src/elements/heap_map.dart"],["observatory","lib/src/elements/io_view.dart"],["observatory","lib/src/elements/isolate_ref.dart"],["observatory","lib/src/elements/isolate_summary.dart"],["observatory","lib/src/elements/isolate_view.dart"],["observatory","lib/src/elements/instance_view.dart"],["observatory","lib/src/elements/json_view.dart"],["observatory","lib/src/elements/library_view.dart"],["observatory","lib/src/elements/heap_profile.dart"],["observatory","lib/src/elements/sliding_checkbox.dart"],["observatory","lib/src/elements/isolate_profile.dart"],["observatory","lib/src/elements/script_view.dart"],["observatory","lib/src/elements/stack_frame.dart"],["observatory","lib/src/elements/stack_trace.dart"],["observatory","lib/src/elements/vm_view.dart"],["observatory","lib/src/elements/service_view.dart"],["observatory","lib/src/elements/response_viewer.dart"],["observatory","lib/src/elements/observatory_application.dart"],["observatory","lib/src/elements/service_exception_view.dart"],["observatory","lib/src/elements/service_error_view.dart"],["observatory","lib/src/elements/vm_ref.dart"],["observatory","web/main.dart"]]}
|
||||
{"experimental_bootstrap":false,"script_ids":[["observatory","lib/src/elements/curly_block.dart"],["observatory","lib/src/elements/observatory_element.dart"],["observatory","lib/src/elements/service_ref.dart"],["observatory","lib/src/elements/instance_ref.dart"],["observatory","lib/src/elements/action_link.dart"],["observatory","lib/src/elements/nav_bar.dart"],["observatory","lib/src/elements/breakpoint_list.dart"],["observatory","lib/src/elements/class_ref.dart"],["observatory","lib/src/elements/eval_box.dart"],["observatory","lib/src/elements/eval_link.dart"],["observatory","lib/src/elements/field_ref.dart"],["observatory","lib/src/elements/function_ref.dart"],["observatory","lib/src/elements/library_ref.dart"],["observatory","lib/src/elements/script_ref.dart"],["observatory","lib/src/elements/class_view.dart"],["observatory","lib/src/elements/code_ref.dart"],["observatory","lib/src/elements/code_view.dart"],["observatory","lib/src/elements/collapsible_content.dart"],["observatory","lib/src/elements/error_view.dart"],["observatory","lib/src/elements/field_view.dart"],["observatory","lib/src/elements/stack_frame.dart"],["observatory","lib/src/elements/flag_list.dart"],["observatory","lib/src/elements/script_inset.dart"],["observatory","lib/src/elements/function_view.dart"],["observatory","lib/src/elements/heap_map.dart"],["observatory","lib/src/elements/io_view.dart"],["observatory","lib/src/elements/isolate_ref.dart"],["observatory","lib/src/elements/isolate_summary.dart"],["observatory","lib/src/elements/isolate_view.dart"],["observatory","lib/src/elements/instance_view.dart"],["observatory","lib/src/elements/json_view.dart"],["observatory","lib/src/elements/library_view.dart"],["observatory","lib/src/elements/heap_profile.dart"],["observatory","lib/src/elements/sliding_checkbox.dart"],["observatory","lib/src/elements/isolate_profile.dart"],["observatory","lib/src/elements/script_view.dart"],["observatory","lib/src/elements/stack_trace.dart"],["observatory","lib/src/elements/vm_view.dart"],["observatory","lib/src/elements/service_view.dart"],["observatory","lib/src/elements/response_viewer.dart"],["observatory","lib/src/elements/observatory_application.dart"],["observatory","lib/src/elements/service_exception_view.dart"],["observatory","lib/src/elements/service_error_view.dart"],["observatory","lib/src/elements/vm_ref.dart"],["observatory","web/main.dart"]]}
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1 +1 @@
|
|||
{"experimental_bootstrap":false,"script_ids":[["observatory","lib/src/elements/curly_block.dart"],["observatory","lib/src/elements/observatory_element.dart"],["observatory","lib/src/elements/service_ref.dart"],["observatory","lib/src/elements/instance_ref.dart"],["observatory","lib/src/elements/action_link.dart"],["observatory","lib/src/elements/nav_bar.dart"],["observatory","lib/src/elements/breakpoint_list.dart"],["observatory","lib/src/elements/class_ref.dart"],["observatory","lib/src/elements/eval_box.dart"],["observatory","lib/src/elements/eval_link.dart"],["observatory","lib/src/elements/field_ref.dart"],["observatory","lib/src/elements/function_ref.dart"],["observatory","lib/src/elements/library_ref.dart"],["observatory","lib/src/elements/script_ref.dart"],["observatory","lib/src/elements/class_view.dart"],["observatory","lib/src/elements/code_ref.dart"],["observatory","lib/src/elements/code_view.dart"],["observatory","lib/src/elements/collapsible_content.dart"],["observatory","lib/src/elements/error_view.dart"],["observatory","lib/src/elements/field_view.dart"],["observatory","lib/src/elements/script_inset.dart"],["observatory","lib/src/elements/function_view.dart"],["observatory","lib/src/elements/heap_map.dart"],["observatory","lib/src/elements/io_view.dart"],["observatory","lib/src/elements/isolate_ref.dart"],["observatory","lib/src/elements/isolate_summary.dart"],["observatory","lib/src/elements/isolate_view.dart"],["observatory","lib/src/elements/instance_view.dart"],["observatory","lib/src/elements/json_view.dart"],["observatory","lib/src/elements/library_view.dart"],["observatory","lib/src/elements/heap_profile.dart"],["observatory","lib/src/elements/sliding_checkbox.dart"],["observatory","lib/src/elements/isolate_profile.dart"],["observatory","lib/src/elements/script_view.dart"],["observatory","lib/src/elements/stack_frame.dart"],["observatory","lib/src/elements/stack_trace.dart"],["observatory","lib/src/elements/vm_view.dart"],["observatory","lib/src/elements/service_view.dart"],["observatory","lib/src/elements/response_viewer.dart"],["observatory","lib/src/elements/observatory_application.dart"],["observatory","lib/src/elements/service_exception_view.dart"],["observatory","lib/src/elements/service_error_view.dart"],["observatory","lib/src/elements/vm_ref.dart"],["observatory","web/main.dart"]]}
|
||||
{"experimental_bootstrap":false,"script_ids":[["observatory","lib/src/elements/curly_block.dart"],["observatory","lib/src/elements/observatory_element.dart"],["observatory","lib/src/elements/service_ref.dart"],["observatory","lib/src/elements/instance_ref.dart"],["observatory","lib/src/elements/action_link.dart"],["observatory","lib/src/elements/nav_bar.dart"],["observatory","lib/src/elements/breakpoint_list.dart"],["observatory","lib/src/elements/class_ref.dart"],["observatory","lib/src/elements/eval_box.dart"],["observatory","lib/src/elements/eval_link.dart"],["observatory","lib/src/elements/field_ref.dart"],["observatory","lib/src/elements/function_ref.dart"],["observatory","lib/src/elements/library_ref.dart"],["observatory","lib/src/elements/script_ref.dart"],["observatory","lib/src/elements/class_view.dart"],["observatory","lib/src/elements/code_ref.dart"],["observatory","lib/src/elements/code_view.dart"],["observatory","lib/src/elements/collapsible_content.dart"],["observatory","lib/src/elements/error_view.dart"],["observatory","lib/src/elements/field_view.dart"],["observatory","lib/src/elements/stack_frame.dart"],["observatory","lib/src/elements/flag_list.dart"],["observatory","lib/src/elements/script_inset.dart"],["observatory","lib/src/elements/function_view.dart"],["observatory","lib/src/elements/heap_map.dart"],["observatory","lib/src/elements/io_view.dart"],["observatory","lib/src/elements/isolate_ref.dart"],["observatory","lib/src/elements/isolate_summary.dart"],["observatory","lib/src/elements/isolate_view.dart"],["observatory","lib/src/elements/instance_view.dart"],["observatory","lib/src/elements/json_view.dart"],["observatory","lib/src/elements/library_view.dart"],["observatory","lib/src/elements/heap_profile.dart"],["observatory","lib/src/elements/sliding_checkbox.dart"],["observatory","lib/src/elements/isolate_profile.dart"],["observatory","lib/src/elements/script_view.dart"],["observatory","lib/src/elements/stack_trace.dart"],["observatory","lib/src/elements/vm_view.dart"],["observatory","lib/src/elements/service_view.dart"],["observatory","lib/src/elements/response_viewer.dart"],["observatory","lib/src/elements/observatory_application.dart"],["observatory","lib/src/elements/service_exception_view.dart"],["observatory","lib/src/elements/service_error_view.dart"],["observatory","lib/src/elements/vm_ref.dart"],["observatory","web/main.dart"]]}
|
File diff suppressed because it is too large
Load diff
|
@ -14,6 +14,7 @@
|
|||
<link rel="import" href="src/elements/eval_link.html">
|
||||
<link rel="import" href="src/elements/field_ref.html">
|
||||
<link rel="import" href="src/elements/field_view.html">
|
||||
<link rel="import" href="src/elements/flag_list.html">
|
||||
<link rel="import" href="src/elements/function_ref.html">
|
||||
<link rel="import" href="src/elements/function_view.html">
|
||||
<link rel="import" href="src/elements/heap_map.html">
|
||||
|
|
|
@ -56,7 +56,12 @@ a:hover {
|
|||
|
||||
em {
|
||||
color: inherit;
|
||||
font-style:italic;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
b {
|
||||
color: inherit;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
hr {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<head>
|
||||
<link rel="import" href="nav_bar.html">
|
||||
<link rel="import" href="observatory_element.html">
|
||||
<link rel="import" href="stack_frame.html">
|
||||
</head>
|
||||
|
||||
<polymer-element name="flag-list" extends="observatory-element">
|
||||
<template>
|
||||
<link rel="stylesheet" href="css/shared.css">
|
||||
<nav-bar>
|
||||
<top-nav-menu></top-nav-menu>
|
||||
<nav-menu link="{{ flagList.isolate.relativeHashLink('flags') }}" anchor="flags" last="{{ true }}"></nav-menu>
|
||||
<nav-refresh callback="{{ refresh }}"></nav-refresh>
|
||||
</nav-bar>
|
||||
|
||||
<div class="content-centered">
|
||||
<template if="{{ flagList['modifiedFlags'].isNotEmpty }}">
|
||||
<h1>Modified Flags</h1>
|
||||
<br>
|
||||
<template repeat="{{ flag in flagList['modifiedFlags'] }}">
|
||||
<flag-item flag="{{ flag }}"></flag-item>
|
||||
<br>
|
||||
</template>
|
||||
<hr>
|
||||
</template>
|
||||
|
||||
<h1>Unmodified Flags</h1>
|
||||
<br>
|
||||
<template if="{{ flagList['unmodifiedFlags'].isEmpty }}">
|
||||
<em>None</em>
|
||||
</template>
|
||||
<template if="{{ flagList['unmodifiedFlags'].isNotEmpty }}">
|
||||
<template repeat="{{ flag in flagList['unmodifiedFlags'] }}">
|
||||
<flag-item flag="{{ flag }}"></flag-item>
|
||||
<br>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</polymer-element>
|
||||
|
||||
<polymer-element name="flag-item" extends="observatory-element">
|
||||
<template>
|
||||
<link rel="stylesheet" href="css/shared.css">
|
||||
<span style="color:#aaa">// {{ flag['comment'] }}</span>
|
||||
<div style="padding: 3px 0">
|
||||
<b>{{ flag['name'] }}</b>
|
||||
=
|
||||
{{ flag['valueAsString'] }}
|
||||
</div>
|
||||
</template>
|
||||
</polymer-element>
|
||||
|
||||
<script type="application/dart" src="flag_list.dart"></script>
|
|
@ -61,6 +61,21 @@
|
|||
</template>
|
||||
</polymer-element>
|
||||
|
||||
<polymer-element name="io-ref" extends="service-ref">
|
||||
<template>
|
||||
<link rel="stylesheet" href="css/shared.css">
|
||||
<template if="{{ ref.serviceType == 'Socket' }}">
|
||||
<io-socket-ref ref="{{ ref }}"></io-socket-ref>
|
||||
</template>
|
||||
<template if="{{ ref.serviceType == 'HttpServer' }}">
|
||||
<io-http-server-ref ref="{{ ref }}"></io-http-server-ref>
|
||||
</template>
|
||||
<template if="{{ ref.serviceType == 'WebSocket' }}">
|
||||
<io-web-socket-ref ref="{{ ref }}"></io-web-socket-ref>
|
||||
</template>
|
||||
</template>
|
||||
</polymer-element>
|
||||
|
||||
<polymer-element name="io-http-server-list-view" extends="observatory-element">
|
||||
<template>
|
||||
<link rel="stylesheet" href="css/shared.css">
|
||||
|
@ -186,6 +201,12 @@
|
|||
<br>
|
||||
|
||||
<div class="memberList">
|
||||
<template if="{{ socket['owner'] != null }}">
|
||||
<div class="memberItem">
|
||||
<div class="memberName">Owner</div>
|
||||
<div class="memberValue"><io-ref ref="{{ socket['owner'] }}"></io-ref></div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="memberItem">
|
||||
<div class="memberName">Address</div>
|
||||
<div class="memberValue">{{ socket['address'] }}</div>
|
||||
|
|
|
@ -36,6 +36,12 @@
|
|||
<div class="memberName">asserts enabled</div>
|
||||
<div class="memberValue">{{ vm.assertsEnabled }}</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="memberItem">
|
||||
<div class="memberValue">
|
||||
See <a href="#/flags">flags</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ export 'package:observatory/src/elements/eval_box.dart';
|
|||
export 'package:observatory/src/elements/eval_link.dart';
|
||||
export 'package:observatory/src/elements/field_ref.dart';
|
||||
export 'package:observatory/src/elements/field_view.dart';
|
||||
export 'package:observatory/src/elements/flag_list.dart';
|
||||
export 'package:observatory/src/elements/function_ref.dart';
|
||||
export 'package:observatory/src/elements/function_view.dart';
|
||||
export 'package:observatory/src/elements/heap_map.dart';
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
<link rel="import" href="src/elements/eval_link.html">
|
||||
<link rel="import" href="src/elements/field_ref.html">
|
||||
<link rel="import" href="src/elements/field_view.html">
|
||||
<link rel="import" href="src/elements/flag_list.html">
|
||||
<link rel="import" href="src/elements/function_ref.html">
|
||||
<link rel="import" href="src/elements/function_view.html">
|
||||
<link rel="import" href="src/elements/heap_map.html">
|
||||
|
|
|
@ -56,7 +56,12 @@ a:hover {
|
|||
|
||||
em {
|
||||
color: inherit;
|
||||
font-style:italic;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
b {
|
||||
color: inherit;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
hr {
|
||||
|
|
27
runtime/bin/vmservice/client/lib/src/elements/flag_list.dart
Normal file
27
runtime/bin/vmservice/client/lib/src/elements/flag_list.dart
Normal file
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2013, the Dart 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.
|
||||
|
||||
library flag_list_element;
|
||||
|
||||
import 'package:polymer/polymer.dart';
|
||||
import 'observatory_element.dart';
|
||||
import 'package:observatory/service.dart';
|
||||
|
||||
@CustomTag('flag-list')
|
||||
class FlagListElement extends ObservatoryElement {
|
||||
@published ServiceMap flagList;
|
||||
|
||||
FlagListElement.created() : super.created();
|
||||
|
||||
void refresh(var done) {
|
||||
flagList.reload().whenComplete(done);
|
||||
}
|
||||
}
|
||||
|
||||
@CustomTag('flag-item')
|
||||
class FlagItemElement extends ObservatoryElement {
|
||||
@published ObservableMap flag;
|
||||
|
||||
FlagItemElement.created() : super.created();
|
||||
}
|
55
runtime/bin/vmservice/client/lib/src/elements/flag_list.html
Normal file
55
runtime/bin/vmservice/client/lib/src/elements/flag_list.html
Normal file
|
@ -0,0 +1,55 @@
|
|||
<head>
|
||||
<link rel="import" href="nav_bar.html">
|
||||
<link rel="import" href="observatory_element.html">
|
||||
<link rel="import" href="stack_frame.html">
|
||||
</head>
|
||||
|
||||
<polymer-element name="flag-list" extends="observatory-element">
|
||||
<template>
|
||||
<link rel="stylesheet" href="css/shared.css">
|
||||
<nav-bar>
|
||||
<top-nav-menu></top-nav-menu>
|
||||
<nav-menu link="{{ flagList.isolate.relativeHashLink('flags') }}" anchor="flags" last="{{ true }}"></nav-menu>
|
||||
<nav-refresh callback="{{ refresh }}"></nav-refresh>
|
||||
</nav-bar>
|
||||
|
||||
<div class="content-centered">
|
||||
<template if="{{ flagList['modifiedFlags'].isNotEmpty }}">
|
||||
<h1>Modified Flags</h1>
|
||||
<br>
|
||||
<template repeat="{{ flag in flagList['modifiedFlags'] }}">
|
||||
<flag-item flag="{{ flag }}"></flag-item>
|
||||
<br>
|
||||
</template>
|
||||
<hr>
|
||||
</template>
|
||||
|
||||
<h1>Unmodified Flags</h1>
|
||||
<br>
|
||||
<template if="{{ flagList['unmodifiedFlags'].isEmpty }}">
|
||||
<em>None</em>
|
||||
</template>
|
||||
<template if="{{ flagList['unmodifiedFlags'].isNotEmpty }}">
|
||||
<template repeat="{{ flag in flagList['unmodifiedFlags'] }}">
|
||||
<flag-item flag="{{ flag }}"></flag-item>
|
||||
<br>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
</polymer-element>
|
||||
|
||||
<polymer-element name="flag-item" extends="observatory-element">
|
||||
<template>
|
||||
<link rel="stylesheet" href="css/shared.css">
|
||||
<span style="color:#aaa">// {{ flag['comment'] }}</span>
|
||||
<div style="padding: 3px 0">
|
||||
<b>{{ flag['name'] }}</b>
|
||||
=
|
||||
{{ flag['valueAsString'] }}
|
||||
</div>
|
||||
</template>
|
||||
</polymer-element>
|
||||
|
||||
<script type="application/dart" src="flag_list.dart"></script>
|
|
@ -44,6 +44,10 @@ class ServiceObjectViewElement extends ObservatoryElement {
|
|||
FieldViewElement element = new Element.tag('field-view');
|
||||
element.field = object;
|
||||
return element;
|
||||
case 'FlagList':
|
||||
FlagListElement element = new Element.tag('flag-list');
|
||||
element.flagList = object;
|
||||
return element;
|
||||
case 'Function':
|
||||
FunctionViewElement element = new Element.tag('function-view');
|
||||
element.function = object;
|
||||
|
|
|
@ -36,6 +36,12 @@
|
|||
<div class="memberName">asserts enabled</div>
|
||||
<div class="memberValue">{{ vm.assertsEnabled }}</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="memberItem">
|
||||
<div class="memberValue">
|
||||
See <a href="#/flags">flags</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ abstract class ServiceObject extends Observable {
|
|||
String _serviceType;
|
||||
|
||||
/// The complete service url of this object.
|
||||
@reflectable String get link => isolate.relativeLink(_id);
|
||||
@reflectable String get link => _owner.relativeLink(_id);
|
||||
|
||||
/// The complete service url of this object with a '#/' prefix.
|
||||
// TODO(turnidge): Figure out why using a getter here messes up polymer.
|
||||
|
@ -179,6 +179,7 @@ abstract class VM extends ServiceObjectOwner {
|
|||
@reflectable Iterable<Isolate> get isolates => _isolateCache.values;
|
||||
|
||||
@reflectable String get link => '$id';
|
||||
@reflectable String relativeLink(String id) => '$id';
|
||||
|
||||
@observable String version = 'unknown';
|
||||
@observable String architecture = 'unknown';
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "vm/flags.h"
|
||||
|
||||
#include "platform/assert.h"
|
||||
#include "vm/json_stream.h"
|
||||
#include "vm/os.h"
|
||||
|
||||
namespace dart {
|
||||
|
@ -13,11 +14,13 @@ DEFINE_FLAG(bool, print_flags, false, "Print flags as they are being parsed.");
|
|||
DEFINE_FLAG(bool, ignore_unrecognized_flags, false,
|
||||
"Ignore unrecognized flags.");
|
||||
|
||||
// List of registered flags.
|
||||
Flag* Flags::flags_ = NULL;
|
||||
|
||||
bool Flags::initialized_ = false;
|
||||
|
||||
// List of registered flags.
|
||||
Flag** Flags::flags_ = NULL;
|
||||
intptr_t Flags::capacity_ = 0;
|
||||
intptr_t Flags::num_flags_ = 0;
|
||||
|
||||
class Flag {
|
||||
public:
|
||||
enum FlagType {
|
||||
|
@ -72,7 +75,6 @@ class Flag {
|
|||
return (type_ == kBoolean) && (bool_ptr_ == NULL);
|
||||
}
|
||||
|
||||
Flag* next_;
|
||||
const char* name_;
|
||||
const char* comment_;
|
||||
union {
|
||||
|
@ -83,16 +85,16 @@ class Flag {
|
|||
FlagHandler handler_;
|
||||
};
|
||||
FlagType type_;
|
||||
bool changed_;
|
||||
};
|
||||
|
||||
|
||||
Flag* Flags::Lookup(const char* name) {
|
||||
Flag* cur = Flags::flags_;
|
||||
while (cur != NULL) {
|
||||
if (strcmp(cur->name_, name) == 0) {
|
||||
return cur;
|
||||
for (intptr_t i = 0; i < num_flags_; i++) {
|
||||
Flag* flag = flags_[i];
|
||||
if (strcmp(flag->name_, name) == 0) {
|
||||
return flag;
|
||||
}
|
||||
cur = cur->next_;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -107,6 +109,27 @@ bool Flags::IsSet(const char* name) {
|
|||
}
|
||||
|
||||
|
||||
void Flags::AddFlag(Flag* flag) {
|
||||
ASSERT(!initialized_);
|
||||
if (num_flags_ == capacity_) {
|
||||
if (flags_ == NULL) {
|
||||
capacity_ = 256;
|
||||
flags_ = new Flag*[capacity_];
|
||||
} else {
|
||||
intptr_t new_capacity = capacity_ * 2;
|
||||
Flag** new_flags = new Flag*[new_capacity];
|
||||
for (intptr_t i = 0; i < num_flags_; i++) {
|
||||
new_flags[i] = flags_[i];
|
||||
}
|
||||
delete [] flags_;
|
||||
flags_ = new_flags;
|
||||
capacity_ = new_capacity;
|
||||
}
|
||||
}
|
||||
flags_[num_flags_++] = flag;
|
||||
}
|
||||
|
||||
|
||||
bool Flags::Register_bool(bool* addr,
|
||||
const char* name,
|
||||
bool default_value,
|
||||
|
@ -117,9 +140,7 @@ bool Flags::Register_bool(bool* addr,
|
|||
return default_value;
|
||||
}
|
||||
flag = new Flag(name, comment, addr, Flag::kBoolean);
|
||||
flag->next_ = Flags::flags_;
|
||||
Flags::flags_ = flag;
|
||||
|
||||
AddFlag(flag);
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
@ -131,8 +152,7 @@ int Flags::Register_int(int* addr,
|
|||
ASSERT(Lookup(name) == NULL);
|
||||
|
||||
Flag* flag = new Flag(name, comment, addr, Flag::kInteger);
|
||||
flag->next_ = Flags::flags_;
|
||||
Flags::flags_ = flag;
|
||||
AddFlag(flag);
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
@ -144,8 +164,7 @@ const char* Flags::Register_charp(charp* addr,
|
|||
const char* comment) {
|
||||
ASSERT(Lookup(name) == NULL);
|
||||
Flag* flag = new Flag(name, comment, addr, Flag::kString);
|
||||
flag->next_ = Flags::flags_;
|
||||
Flags::flags_ = flag;
|
||||
AddFlag(flag);
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
@ -155,8 +174,7 @@ bool Flags::Register_func(FlagHandler handler,
|
|||
const char* comment) {
|
||||
ASSERT(Lookup(name) == NULL);
|
||||
Flag* flag = new Flag(name, comment, handler);
|
||||
flag->next_ = Flags::flags_;
|
||||
Flags::flags_ = flag;
|
||||
AddFlag(flag);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -171,6 +189,51 @@ static void Normalize(char* s) {
|
|||
}
|
||||
|
||||
|
||||
bool Flags::SetFlagFromString(Flag* flag, const char* argument) {
|
||||
ASSERT(!flag->IsUnrecognized());
|
||||
switch (flag->type_) {
|
||||
case Flag::kBoolean: {
|
||||
if (strcmp(argument, "true") == 0) {
|
||||
*flag->bool_ptr_ = true;
|
||||
} else if (strcmp(argument, "false") == 0) {
|
||||
*flag->bool_ptr_ = false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Flag::kString: {
|
||||
*flag->charp_ptr_ = argument == NULL ? NULL : strdup(argument);
|
||||
break;
|
||||
}
|
||||
case Flag::kInteger: {
|
||||
char* endptr = NULL;
|
||||
int val = strtol(argument, &endptr, 10);
|
||||
if (endptr != argument) {
|
||||
*flag->int_ptr_ = val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Flag::kFunc: {
|
||||
if (strcmp(argument, "true") == 0) {
|
||||
(flag->handler_)(true);
|
||||
} else if (strcmp(argument, "false") == 0) {
|
||||
(flag->handler_)(false);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
flag->changed_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Flags::Parse(const char* option) {
|
||||
// Find the beginning of the option argument, if it exists.
|
||||
const char* equals = option;
|
||||
|
@ -220,43 +283,9 @@ void Flags::Parse(const char* option) {
|
|||
// Only set values for recognized flags, skip collected
|
||||
// unrecognized flags.
|
||||
if (!flag->IsUnrecognized()) {
|
||||
switch (flag->type_) {
|
||||
case Flag::kBoolean: {
|
||||
if (strcmp(argument, "true") == 0) {
|
||||
*flag->bool_ptr_ = true;
|
||||
} else if (strcmp(argument, "false") == 0) {
|
||||
*flag->bool_ptr_ = false;
|
||||
} else {
|
||||
OS::Print("Ignoring flag: %s is a bool flag.\n", name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Flag::kString: {
|
||||
*flag->charp_ptr_ = argument == NULL ? NULL : strdup(argument);
|
||||
break;
|
||||
}
|
||||
case Flag::kInteger: {
|
||||
char* endptr = NULL;
|
||||
int val = strtol(argument, &endptr, 10);
|
||||
if (endptr != argument) {
|
||||
*flag->int_ptr_ = val;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Flag::kFunc: {
|
||||
if (strcmp(argument, "true") == 0) {
|
||||
(flag->handler_)(true);
|
||||
} else if (strcmp(argument, "false") == 0) {
|
||||
(flag->handler_)(false);
|
||||
} else {
|
||||
OS::Print("Ignoring flag: %s is a bool flag.\n", name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
if (!SetFlagFromString(flag, argument)) {
|
||||
OS::Print("Ignoring flag: %s is an invalid value for flag %s\n",
|
||||
argument, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,13 +303,20 @@ static bool IsValidFlag(const char* name,
|
|||
}
|
||||
|
||||
|
||||
int Flags::CompareFlagNames(const void* left, const void* right) {
|
||||
const Flag* left_flag = *reinterpret_cast<const Flag* const *>(left);
|
||||
const Flag* right_flag = *reinterpret_cast<const Flag* const *>(right);
|
||||
return strcmp(left_flag->name_, right_flag->name_);
|
||||
}
|
||||
|
||||
|
||||
bool Flags::ProcessCommandLineFlags(int number_of_vm_flags,
|
||||
const char** vm_flags) {
|
||||
if (initialized_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
qsort(flags_, num_flags_, sizeof flags_[0], CompareFlagNames);
|
||||
|
||||
const char* kPrefix = "--";
|
||||
const intptr_t kPrefixLen = strlen(kPrefix);
|
||||
|
@ -295,8 +331,8 @@ bool Flags::ProcessCommandLineFlags(int number_of_vm_flags,
|
|||
|
||||
if (!FLAG_ignore_unrecognized_flags) {
|
||||
int unrecognized_count = 0;
|
||||
Flag* flag = Flags::flags_;
|
||||
while (flag != NULL) {
|
||||
for (intptr_t j = 0; j < num_flags_; j++) {
|
||||
Flag* flag = flags_[j];
|
||||
if (flag->IsUnrecognized()) {
|
||||
if (unrecognized_count == 0) {
|
||||
OS::PrintErr("Unrecognized flags: %s", flag->name_);
|
||||
|
@ -305,7 +341,6 @@ bool Flags::ProcessCommandLineFlags(int number_of_vm_flags,
|
|||
}
|
||||
unrecognized_count++;
|
||||
}
|
||||
flag = flag->next_;
|
||||
}
|
||||
if (unrecognized_count > 0) {
|
||||
OS::PrintErr("\n");
|
||||
|
@ -315,36 +350,93 @@ bool Flags::ProcessCommandLineFlags(int number_of_vm_flags,
|
|||
if (FLAG_print_flags) {
|
||||
PrintFlags();
|
||||
}
|
||||
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Flags::SetFlag(const char* name,
|
||||
const char* value,
|
||||
const char** error) {
|
||||
Flag* flag = Lookup(name);
|
||||
if (flag == NULL) {
|
||||
*error = "Cannot set flag: flag not found";
|
||||
return false;
|
||||
}
|
||||
if (!SetFlagFromString(flag, value)) {
|
||||
*error = "Cannot set flag: invalid value";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int Flags::CompareFlagNames(const void* left, const void* right) {
|
||||
const Flag* left_flag = *reinterpret_cast<const Flag* const *>(left);
|
||||
const Flag* right_flag = *reinterpret_cast<const Flag* const *>(right);
|
||||
return strcmp(left_flag->name_, right_flag->name_);
|
||||
void Flags::PrintFlags() {
|
||||
OS::Print("Flag settings:\n");
|
||||
for (intptr_t i = 0; i < num_flags_; ++i) {
|
||||
flags_[i]->Print();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Flags::PrintFlags() {
|
||||
OS::Print("Flag settings:\n");
|
||||
Flag* flag = Flags::flags_;
|
||||
int num_flags = 0;
|
||||
while (flag != NULL) {
|
||||
num_flags++;
|
||||
flag = flag->next_;
|
||||
}
|
||||
Flag** flag_array = new Flag*[num_flags];
|
||||
flag = Flags::flags_;
|
||||
for (int i = 0; i < num_flags; ++i, flag = flag->next_) {
|
||||
flag_array[i] = flag;
|
||||
}
|
||||
|
||||
qsort(flag_array, num_flags, sizeof flag_array[0], CompareFlagNames);
|
||||
|
||||
for (int i = 0; i < num_flags; ++i) {
|
||||
flag_array[i]->Print();
|
||||
}
|
||||
delete[] flag_array;
|
||||
void Flags::PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag) {
|
||||
if (flag->IsUnrecognized() || flag->type_ == Flag::kFunc) {
|
||||
return;
|
||||
}
|
||||
JSONObject jsflag(jsarr);
|
||||
jsflag.AddProperty("name", flag->name_);
|
||||
jsflag.AddProperty("comment", flag->comment_);
|
||||
switch (flag->type_) {
|
||||
case Flag::kBoolean: {
|
||||
jsflag.AddProperty("flagType", "bool");
|
||||
jsflag.AddProperty("valueAsString",
|
||||
(*flag->bool_ptr_ ? "true" : "false"));
|
||||
break;
|
||||
}
|
||||
case Flag::kInteger: {
|
||||
jsflag.AddProperty("flagType", "int");
|
||||
jsflag.AddPropertyF("valueAsString", "%d", *flag->int_ptr_);
|
||||
break;
|
||||
}
|
||||
case Flag::kString: {
|
||||
jsflag.AddProperty("flagType", "string");
|
||||
if (flag->charp_ptr_ != NULL) {
|
||||
jsflag.AddPropertyF("valueAsString", "%s", *flag->charp_ptr_);
|
||||
} else {
|
||||
// valueAsString missing means NULL.
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Flags::PrintJSON(JSONStream* js) {
|
||||
JSONObject jsobj(js);
|
||||
jsobj.AddProperty("type", "FlagList");
|
||||
jsobj.AddProperty("id", "flags");
|
||||
|
||||
{
|
||||
JSONArray jsarr(&jsobj, "unmodifiedFlags");
|
||||
for (intptr_t i = 0; i < num_flags_; ++i) {
|
||||
Flag* flag = flags_[i];
|
||||
if (!flag->changed_) {
|
||||
PrintFlagToJSONArray(&jsarr, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
JSONArray jsarr(&jsobj, "modifiedFlags");
|
||||
for (intptr_t i = 0; i < num_flags_; ++i) {
|
||||
Flag* flag = flags_[i];
|
||||
if (flag->changed_) {
|
||||
PrintFlagToJSONArray(&jsarr, flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -36,8 +36,10 @@ namespace dart {
|
|||
|
||||
typedef void (*FlagHandler)(bool value);
|
||||
|
||||
// Forward declaration.
|
||||
// Forward declarations.
|
||||
class Flag;
|
||||
class JSONArray;
|
||||
class JSONStream;
|
||||
|
||||
class Flags {
|
||||
public:
|
||||
|
@ -68,17 +70,31 @@ class Flags {
|
|||
|
||||
static bool Initialized() { return initialized_; }
|
||||
|
||||
static void PrintJSON(JSONStream* js);
|
||||
|
||||
static bool SetFlag(const char* name,
|
||||
const char* value,
|
||||
const char** error);
|
||||
|
||||
private:
|
||||
static Flag* flags_;
|
||||
static Flag** flags_;
|
||||
static intptr_t capacity_;
|
||||
static intptr_t num_flags_;
|
||||
|
||||
static bool initialized_;
|
||||
|
||||
static void AddFlag(Flag* flag);
|
||||
|
||||
static bool SetFlagFromString(Flag* flag, const char* argument);
|
||||
|
||||
static void Parse(const char* option);
|
||||
|
||||
static int CompareFlagNames(const void* left, const void* right);
|
||||
|
||||
static void PrintFlags();
|
||||
|
||||
static void PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag);
|
||||
|
||||
// Testing needs direct access to private methods.
|
||||
friend void Dart_TestParseFlags();
|
||||
|
||||
|
|
|
@ -1933,7 +1933,8 @@ static bool HandleVM(JSONStream* js) {
|
|||
JSONObject jsobj(js);
|
||||
jsobj.AddProperty("type", "VM");
|
||||
jsobj.AddProperty("id", "vm");
|
||||
jsobj.AddProperty("architecture", CPU::Id());
|
||||
jsobj.AddProperty("targetCPU", CPU::Id());
|
||||
jsobj.AddProperty("hostCPU", HostCPUFeatures::hardware());
|
||||
jsobj.AddProperty("version", Version::String());
|
||||
jsobj.AddProperty("assertsEnabled", FLAG_enable_asserts);
|
||||
jsobj.AddProperty("typeChecksEnabled", FLAG_enable_type_checks);
|
||||
|
@ -1953,9 +1954,47 @@ static bool HandleVM(JSONStream* js) {
|
|||
}
|
||||
|
||||
|
||||
static bool HandleFlags(JSONStream* js) {
|
||||
if (js->num_arguments() == 1) {
|
||||
Flags::PrintJSON(js);
|
||||
return true;
|
||||
} else if (js->num_arguments() == 2) {
|
||||
const char* arg = js->GetArgument(1);
|
||||
if (strcmp(arg, "set") == 0) {
|
||||
if (js->num_arguments() > 2) {
|
||||
PrintError(js, "expected at most 2 arguments but found %" Pd "\n",
|
||||
js->num_arguments());
|
||||
} else {
|
||||
if (js->HasOption("name") && js->HasOption("value")) {
|
||||
JSONObject jsobj(js);
|
||||
const char* flag_name = js->LookupOption("name");
|
||||
const char* flag_value = js->LookupOption("value");
|
||||
const char* error = NULL;
|
||||
if (Flags::SetFlag(flag_name, flag_value, &error)) {
|
||||
jsobj.AddProperty("type", "Success");
|
||||
jsobj.AddProperty("id", "");
|
||||
} else {
|
||||
jsobj.AddProperty("type", "Failure");
|
||||
jsobj.AddProperty("id", "");
|
||||
jsobj.AddProperty("message", error);
|
||||
}
|
||||
} else {
|
||||
PrintError(js, "expected to find 'name' and 'value' options");
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
PrintError(js, "Command too long");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static RootMessageHandlerEntry root_handlers[] = {
|
||||
{ "_echo", HandleRootEcho },
|
||||
{ "vm", HandleVM },
|
||||
{ "flags", HandleFlags },
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
namespace dart {
|
||||
|
||||
// This flag is used in the Service_Flags test below.
|
||||
DEFINE_FLAG(bool, service_testing_flag, false, "Comment");
|
||||
|
||||
class ServiceTestMessageHandler : public MessageHandler {
|
||||
public:
|
||||
ServiceTestMessageHandler() : _msg(NULL) {}
|
||||
|
@ -1065,13 +1068,63 @@ TEST_CASE(Service_VM) {
|
|||
Service::HandleRootMessage(service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING("\"type\":\"VM\",\"id\":\"vm\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"architecture\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"targetCPU\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"hostCPU\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"version\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"uptime\"", handler.msg());
|
||||
EXPECT_SUBSTRING("\"isolates\"", handler.msg());
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(Service_Flags) {
|
||||
const char* kScript =
|
||||
"var port;\n" // Set to our mock port by C++.
|
||||
"\n"
|
||||
"main() {\n"
|
||||
"}";
|
||||
|
||||
Isolate* isolate = Isolate::Current();
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
|
||||
// Build a mock message handler and wrap it in a dart port.
|
||||
ServiceTestMessageHandler handler;
|
||||
Dart_Port port_id = PortMap::CreatePort(&handler);
|
||||
Dart_Handle port = Api::NewHandle(isolate, SendPort::New(port_id));
|
||||
EXPECT_VALID(port);
|
||||
EXPECT_VALID(Dart_SetField(lib, NewString("port"), port));
|
||||
|
||||
Instance& service_msg = Instance::Handle();
|
||||
service_msg = Eval(lib, "[port, ['flags'], [], []]");
|
||||
|
||||
// Make sure we can get the FlagList.
|
||||
Service::HandleRootMessage(service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING("\"type\":\"FlagList\",\"id\":\"flags\"", handler.msg());
|
||||
EXPECT_SUBSTRING(
|
||||
"\"name\":\"service_testing_flag\",\"comment\":\"Comment\","
|
||||
"\"flagType\":\"bool\",\"valueAsString\":\"false\"",
|
||||
handler.msg());
|
||||
|
||||
// Modify a flag through the vm service.
|
||||
service_msg = Eval(lib,
|
||||
"[port, ['flags', 'set'], "
|
||||
"['name', 'value'], ['service_testing_flag', 'true']]");
|
||||
Service::HandleRootMessage(service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING("Success", handler.msg());
|
||||
|
||||
// Make sure that the flag changed.
|
||||
service_msg = Eval(lib, "[port, ['flags'], [], []]");
|
||||
Service::HandleRootMessage(service_msg);
|
||||
handler.HandleNextMessage();
|
||||
EXPECT_SUBSTRING(
|
||||
"\"name\":\"service_testing_flag\",\"comment\":\"Comment\","
|
||||
"\"flagType\":\"bool\",\"valueAsString\":\"true\"",
|
||||
handler.msg());
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE(Service_Scripts) {
|
||||
const char* kScript =
|
||||
"var port;\n" // Set to our mock port by C++.
|
||||
|
|
Loading…
Reference in a new issue