Version 2.12.0-158.0.dev
Merge commit '868cb26a2d9093983ed022b77ba26be6cb8fb7f7' into 'dev'
diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni
index 58323d0..1045fdc 100644
--- a/runtime/bin/builtin_impl_sources.gni
+++ b/runtime/bin/builtin_impl_sources.gni
@@ -77,4 +77,5 @@
"eventhandler_test.cc",
"file_test.cc",
"hashmap_test.cc",
+ "priority_heap_test.cc",
]
diff --git a/runtime/bin/eventhandler.cc b/runtime/bin/eventhandler.cc
index 6a02a0f..83e93a0 100644
--- a/runtime/bin/eventhandler.cc
+++ b/runtime/bin/eventhandler.cc
@@ -15,46 +15,6 @@
namespace dart {
namespace bin {
-void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) {
- // Find port if present.
- Timeout* last = NULL;
- Timeout* current = timeouts_;
- while (current != NULL) {
- if (current->port() == port) {
- // Found.
- if (timeout < 0) {
- // Remove from list and delete existing.
- if (last != NULL) {
- last->set_next(current->next());
- } else {
- timeouts_ = current->next();
- }
- delete current;
- } else {
- // Update timeout.
- current->set_timeout(timeout);
- }
- break;
- }
- last = current;
- current = current->next();
- }
- if (current == NULL && timeout >= 0) {
- // Not found, create a new.
- timeouts_ = new Timeout(port, timeout, timeouts_);
- }
- // Clear and find next timeout.
- next_timeout_ = NULL;
- current = timeouts_;
- while (current != NULL) {
- if ((next_timeout_ == NULL) ||
- (current->timeout() < next_timeout_->timeout())) {
- next_timeout_ = current;
- }
- current = current->next();
- }
-}
-
static EventHandler* event_handler = NULL;
static Monitor* shutdown_monitor = NULL;
diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h
index a305f65..69a8e3a 100644
--- a/runtime/bin/eventhandler.h
+++ b/runtime/bin/eventhandler.h
@@ -10,6 +10,7 @@
#include "bin/isolate_data.h"
#include "platform/hashmap.h"
+#include "platform/priority_queue.h"
namespace dart {
namespace bin {
@@ -57,56 +58,39 @@
// clang-format on
class TimeoutQueue {
- private:
- class Timeout {
- public:
- Timeout(Dart_Port port, int64_t timeout, Timeout* next)
- : port_(port), timeout_(timeout), next_(next) {}
-
- Dart_Port port() const { return port_; }
-
- int64_t timeout() const { return timeout_; }
- void set_timeout(int64_t timeout) {
- ASSERT(timeout >= 0);
- timeout_ = timeout;
- }
-
- Timeout* next() const { return next_; }
- void set_next(Timeout* next) { next_ = next; }
-
- private:
- Dart_Port port_;
- int64_t timeout_;
- Timeout* next_;
- };
-
public:
- TimeoutQueue() : next_timeout_(NULL), timeouts_(NULL) {}
+ TimeoutQueue() {}
~TimeoutQueue() {
while (HasTimeout())
RemoveCurrent();
}
- bool HasTimeout() const { return next_timeout_ != NULL; }
+ bool HasTimeout() const { return !timeouts_.IsEmpty(); }
int64_t CurrentTimeout() const {
- ASSERT(next_timeout_ != NULL);
- return next_timeout_->timeout();
+ ASSERT(!timeouts_.IsEmpty());
+ return timeouts_.Minimum().priority;
}
Dart_Port CurrentPort() const {
- ASSERT(next_timeout_ != NULL);
- return next_timeout_->port();
+ ASSERT(!timeouts_.IsEmpty());
+ return timeouts_.Minimum().value;
}
- void RemoveCurrent() { UpdateTimeout(CurrentPort(), -1); }
+ void RemoveCurrent() { timeouts_.RemoveMinimum(); }
- void UpdateTimeout(Dart_Port port, int64_t timeout);
+ void UpdateTimeout(Dart_Port port, int64_t timeout) {
+ if (timeout < 0) {
+ timeouts_.RemoveByValue(port);
+ } else {
+ timeouts_.InsertOrChangePriority(timeout, port);
+ }
+ }
private:
- Timeout* next_timeout_;
- Timeout* timeouts_;
+ PriorityQueue<int64_t, Dart_Port> timeouts_;
+ int64_t next_timeout_;
DISALLOW_COPY_AND_ASSIGN(TimeoutQueue);
};
@@ -399,7 +383,7 @@
intptr_t is_reading;
intptr_t token_count;
- bool IsReady() { return token_count > 0 && is_reading; }
+ bool IsReady() { return token_count > 0 && is_reading != 0; }
};
public:
diff --git a/runtime/bin/priority_heap_test.cc b/runtime/bin/priority_heap_test.cc
new file mode 100644
index 0000000..165f1a4
--- /dev/null
+++ b/runtime/bin/priority_heap_test.cc
@@ -0,0 +1,167 @@
+// Copyright (c) 2020, 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.md file.
+
+#include "vm/unit_test.h"
+
+#include "platform/priority_queue.h"
+
+namespace dart {
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__INCREASING) {
+ const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+ PriorityQueue<word, word> heap;
+ for (word i = 0; i < kSize; i++) {
+ heap.Insert(i, 10 + i);
+ }
+ ASSERT(heap.min_heap_size() == kSize);
+ for (word i = 0; i < kSize; i++) {
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(i, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+ EXPECT(heap.IsEmpty());
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__DECREASING) {
+ const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+ PriorityQueue<word, word> heap;
+ for (word i = kSize - 1; i >= 0; i--) {
+ heap.Insert(i, 10 + i);
+ }
+ ASSERT(heap.min_heap_size() == kSize);
+ for (word i = 0; i < kSize; i++) {
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(i, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+ EXPECT(heap.IsEmpty());
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__DELETE_BY_VALUES) {
+ const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+ PriorityQueue<word, word> heap;
+ for (word i = kSize - 1; i >= 0; i--) {
+ heap.Insert(i, 10 + i);
+ }
+
+ ASSERT(heap.min_heap_size() == kSize);
+
+ EXPECT(heap.RemoveByValue(10 + 0));
+ EXPECT(!heap.RemoveByValue(10 + 0));
+
+ EXPECT(heap.RemoveByValue(10 + 5));
+ EXPECT(!heap.RemoveByValue(10 + 5));
+
+ EXPECT(heap.RemoveByValue(10 + kSize - 1));
+ EXPECT(!heap.RemoveByValue(10 + kSize - 1));
+
+ for (word i = 0; i < kSize; i++) {
+ // Jump over the removed [i]s in the loop.
+ if (i != 0 && i != 5 && i != (kSize - 1)) {
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(i, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+ }
+ EXPECT(heap.IsEmpty());
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__GROW_SHRINK) {
+ const word kSize = 1024;
+ const word kMinimumSize = PriorityQueue<word, word>::kMinimumSize;
+
+ PriorityQueue<word, word> heap;
+ for (word i = 0; i < kSize; i++) {
+ heap.Insert(i, 10 + i);
+ }
+
+ ASSERT(heap.min_heap_size() == kSize);
+
+ for (word i = 0; i < kSize; i++) {
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(i, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+
+ EXPECT(heap.IsEmpty());
+ ASSERT(heap.min_heap_size() == kMinimumSize);
+
+ for (word i = 0; i < kSize; i++) {
+ heap.Insert(i, 10 + i);
+ }
+
+ for (word i = 0; i < kSize; i++) {
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(i, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+
+ EXPECT(heap.IsEmpty());
+ ASSERT(heap.min_heap_size() == kMinimumSize);
+}
+
+UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__CHANGE_PRIORITY) {
+ const word kSize = PriorityQueue<word, word>::kMinimumSize;
+
+ PriorityQueue<word, word> heap;
+ for (word i = 0; i < kSize; i++) {
+ if (i % 2 == 0) {
+ heap.Insert(i, 10 + i);
+ }
+ }
+ ASSERT(heap.min_heap_size() == kSize);
+ for (word i = 0; i < kSize; i++) {
+ bool was_inserted = i % 2 == 0;
+ bool increase = i % 3 == 0;
+ word new_priority = i + (increase ? 100 : -100);
+
+ EXPECT(was_inserted != heap.InsertOrChangePriority(new_priority, 10 + i));
+ }
+
+ for (word i = 0; i < kSize; i++) {
+ bool increase = i % 3 == 0;
+ if (!increase) {
+ word expected_priority = i + (increase ? 100 : -100);
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(expected_priority, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+ }
+ for (word i = 0; i < kSize; i++) {
+ bool increase = i % 3 == 0;
+ if (increase) {
+ word expected_priority = i + (increase ? 100 : -100);
+ EXPECT(!heap.IsEmpty());
+ EXPECT_EQ(expected_priority, heap.Minimum().priority);
+ EXPECT_EQ(10 + i, heap.Minimum().value);
+ EXPECT(heap.ContainsValue(10 + i));
+ heap.RemoveMinimum();
+ EXPECT(!heap.ContainsValue(10 + i));
+ }
+ }
+ EXPECT(heap.IsEmpty());
+}
+
+} // namespace dart.
diff --git a/runtime/lib/errors.cc b/runtime/lib/errors.cc
index cce88cf..049e919 100644
--- a/runtime/lib/errors.cc
+++ b/runtime/lib/errors.cc
@@ -67,9 +67,9 @@
DEFINE_NATIVE_ENTRY(AssertionError_throwNew, 0, 3) {
// No need to type check the arguments. This function can only be called
// internally from the VM.
- const TokenPosition assertion_start = TokenPosition(
+ const TokenPosition assertion_start = TokenPosition::Deserialize(
Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
- const TokenPosition assertion_end = TokenPosition(
+ const TokenPosition assertion_end = TokenPosition::Deserialize(
Smi::CheckedHandle(zone, arguments->NativeArgAt(1)).Value());
const Instance& message =
@@ -151,7 +151,7 @@
DEFINE_NATIVE_ENTRY(TypeError_throwNew, 0, 4) {
// No need to type check the arguments. This function can only be called
// internally from the VM.
- const TokenPosition location = TokenPosition(
+ const TokenPosition location = TokenPosition::Deserialize(
Smi::CheckedHandle(zone, arguments->NativeArgAt(0)).Value());
const Instance& src_value =
Instance::CheckedHandle(zone, arguments->NativeArgAt(1));
@@ -171,7 +171,7 @@
// Return value: none, throws an exception.
DEFINE_NATIVE_ENTRY(FallThroughError_throwNew, 0, 1) {
GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
- TokenPosition fallthrough_pos = TokenPosition(smi_pos.Value());
+ TokenPosition fallthrough_pos = TokenPosition::Deserialize(smi_pos.Value());
const Array& args = Array::Handle(Array::New(2));
@@ -197,7 +197,7 @@
DEFINE_NATIVE_ENTRY(AbstractClassInstantiationError_throwNew, 0, 2) {
GET_NON_NULL_NATIVE_ARGUMENT(Smi, smi_pos, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(String, class_name, arguments->NativeArgAt(1));
- TokenPosition error_pos = TokenPosition(smi_pos.Value());
+ TokenPosition error_pos = TokenPosition::Deserialize(smi_pos.Value());
const Array& args = Array::Handle(Array::New(3));
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index cf1e6ff..4e92dc7 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -447,7 +447,7 @@
if (!AbstractType::InstantiateAndTestSubtype(
&subtype, &supertype, instantiator_type_args, function_type_args)) {
// Throw a dynamic type error.
- TokenPosition location;
+ TokenPosition location = TokenPosition::kNoSource;
{
DartFrameIterator iterator(Thread::Current(),
StackFrameIterator::kNoCrossThreadIteration);
diff --git a/runtime/observatory/tests/service/async_generator_breakpoint_test.dart b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
index 44f5c2a..b607ea8 100644
--- a/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
+++ b/runtime/observatory/tests/service/async_generator_breakpoint_test.dart
@@ -53,15 +53,19 @@
var script = isolate.rootLibrary.scripts[0];
var bp1 = await isolate.addBreakpoint(script, 13);
+ print("BP1 - $bp1");
expect(bp1, isNotNull);
expect(bp1 is Breakpoint, isTrue);
var bp2 = await isolate.addBreakpoint(script, 18);
+ print("BP2 - $bp2");
expect(bp2, isNotNull);
expect(bp2 is Breakpoint, isTrue);
var bp3 = await isolate.addBreakpoint(script, 23);
+ print("BP3 - $bp3");
expect(bp3, isNotNull);
expect(bp3 is Breakpoint, isTrue);
var bp4 = await isolate.addBreakpoint(script, 27);
+ print("BP4 - $bp4");
expect(bp4, isNotNull);
expect(bp4 is Breakpoint, isTrue);
var bp5 = await isolate.addBreakpoint(script, 44);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index bc2bb42..5896d37 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -23,6 +23,10 @@
developer_extension_test: SkipByDesign
get_isolate_after_language_error_test: SkipByDesign
+# The _1 versions of this test can be slow due to stress testing flags.
+[ $mode == debug ]
+async_generator_breakpoint_test: Pass, Slow
+
# Service protocol is not supported in product mode.
[ $mode == product ]
*: SkipByDesign
diff --git a/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart b/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
index 1abcb9f..4f91673 100644
--- a/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
+++ b/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
@@ -53,15 +53,19 @@
var script = isolate.rootLibrary.scripts[0];
var bp1 = await isolate.addBreakpoint(script, 13);
+ print("BP1 - $bp1");
expect(bp1, isNotNull);
expect(bp1 is Breakpoint, isTrue);
var bp2 = await isolate.addBreakpoint(script, 18);
+ print("BP2 - $bp2");
expect(bp2, isNotNull);
expect(bp2 is Breakpoint, isTrue);
var bp3 = await isolate.addBreakpoint(script, 23);
+ print("BP3 - $bp3");
expect(bp3, isNotNull);
expect(bp3 is Breakpoint, isTrue);
var bp4 = await isolate.addBreakpoint(script, 27);
+ print("BP4 - $bp4");
expect(bp4, isNotNull);
expect(bp4 is Breakpoint, isTrue);
var bp5 = await isolate.addBreakpoint(script, 44);
diff --git a/runtime/observatory_2/tests/service_2/service_2.status b/runtime/observatory_2/tests/service_2/service_2.status
index c16feab..874b3f4 100644
--- a/runtime/observatory_2/tests/service_2/service_2.status
+++ b/runtime/observatory_2/tests/service_2/service_2.status
@@ -25,6 +25,10 @@
developer_extension_test: SkipByDesign
get_isolate_after_language_error_test: SkipByDesign
+# The _1 versions of this test can be slow due to stress testing flags.
+[ $mode == debug ]
+async_generator_breakpoint_test: Pass, Slow
+
# Service protocol is not supported in product mode.
[ $mode == product ]
*: SkipByDesign
diff --git a/runtime/platform/priority_queue.h b/runtime/platform/priority_queue.h
new file mode 100644
index 0000000..2064fcc
--- /dev/null
+++ b/runtime/platform/priority_queue.h
@@ -0,0 +1,269 @@
+// Copyright (c) 2020, 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.
+
+#ifndef RUNTIME_PLATFORM_PRIORITY_QUEUE_H_
+#define RUNTIME_PLATFORM_PRIORITY_QUEUE_H_
+
+#include "platform/assert.h"
+#include "platform/globals.h"
+#include "platform/hashmap.h"
+#include "platform/utils.h"
+
+namespace dart {
+
+// A min-priority queue with deletion support.
+//
+// The [PriorityQueue] allows insertion of entries with a priority [P] and a
+// value [V]. The minimum element can be queried in O(1) time.
+// Insertion/Deletion operations have O(N) time.
+//
+// In addition to the normal insert/minimum/remove-minimum operations this
+// priority queue allows deletion-by-value. We have therefore an invariant
+// is that the value must be unique amongst all entries.
+template <typename P, typename V>
+class PriorityQueue {
+ public:
+ static const intptr_t kMinimumSize = 16;
+
+ struct Entry {
+ P priority;
+ V value;
+ };
+
+ PriorityQueue() : hashmap_(&MatchFun, kMinimumSize) {
+ min_heap_size_ = kMinimumSize;
+ min_heap_ =
+ reinterpret_cast<Entry*>(malloc(sizeof(Entry) * min_heap_size_));
+ if (min_heap_ == nullptr) FATAL("Cannot allocate memory.");
+ size_ = 0;
+ }
+
+ ~PriorityQueue() { free(min_heap_); }
+
+ // Whether the queue is empty.
+ bool IsEmpty() const { return size_ == 0; }
+
+ // Inserts a new entry with [priority] and [value], requires there to be no
+ // existing entry with given [value].
+ void Insert(const P& priority, const V& value) {
+ ASSERT(!ContainsValue(value));
+
+ if (size_ == min_heap_size_) {
+ Resize(min_heap_size_ << 1);
+ }
+
+ Set(size_, {priority, value});
+ BubbleUp(size_);
+
+ size_++;
+ }
+
+ // Returns a reference to the minimum entry.
+ //
+ // The caller can access it's priority and value in read-only mode only.
+ const Entry& Minimum() const {
+ ASSERT(!IsEmpty());
+ return min_heap_[0];
+ }
+
+ // Removes the minimum entry.
+ void RemoveMinimum() {
+ ASSERT(!IsEmpty());
+ RemoveAt(0);
+ }
+
+ // Removes an existing entry with the given [value].
+ //
+ // Returns true if such an entry was removed.
+ bool RemoveByValue(const V& value) {
+ auto entry = FindMapEntry(value);
+ if (entry != nullptr) {
+ const intptr_t offset = ValueOfMapEntry(entry);
+ RemoveAt(offset);
+
+ ASSERT(hashmap_.size() == size_);
+ return true;
+ }
+ return false;
+ }
+
+ // Whether the priority queue contains an entry with the given [value].
+ bool ContainsValue(const V& value) { return FindMapEntry(value) != nullptr; }
+
+ // Changes the priority of an existing entry with given [value] or adds a
+ // new entry.
+ bool InsertOrChangePriority(const P& priority, const V& value) {
+ auto map_entry = FindMapEntry(value);
+ if (map_entry == nullptr) {
+ Insert(priority, value);
+ return true;
+ }
+
+ const intptr_t offset = ValueOfMapEntry(map_entry);
+ ASSERT(offset < size_);
+
+ Entry& entry = min_heap_[offset];
+ entry.priority = priority;
+ if (offset == 0) {
+ BubbleDown(offset);
+ } else {
+ intptr_t parent = (offset - 1) / 2;
+ intptr_t diff = entry.priority - min_heap_[parent].priority;
+ if (diff < 0) {
+ BubbleUp(offset);
+ } else if (diff > 0) {
+ BubbleDown(offset);
+ }
+ }
+ return false;
+ }
+
+#ifdef TESTING
+ intptr_t min_heap_size() { return min_heap_size_; }
+#endif // TESTING
+
+ private:
+ // Utility functions dealing with the SimpleHashMap interface.
+ static bool MatchFun(void* key1, void* key2) { return key1 == key2; }
+
+ SimpleHashMap::Entry* FindMapEntry(const V& key, bool insert = false) {
+ return hashmap_.Lookup(CastKey(key), HashKey(key), insert);
+ }
+ void RemoveMapEntry(const V& key) {
+ ASSERT(FindMapEntry(key) != nullptr);
+ hashmap_.Remove(CastKey(key), HashKey(key));
+ }
+ void SetMapEntry(const V& key, intptr_t value) {
+ FindMapEntry(key, /*insert=*/true)->value = reinterpret_cast<void*>(value);
+ }
+ static uint32_t HashKey(const V& key) {
+ return static_cast<uint32_t>(reinterpret_cast<intptr_t>(CastKey(key)));
+ }
+ static intptr_t ValueOfMapEntry(SimpleHashMap::Entry* entry) {
+ return reinterpret_cast<intptr_t>(entry->value);
+ }
+ static void* CastKey(const V& key) {
+ return reinterpret_cast<void*>((const_cast<V&>(key)));
+ }
+
+ void RemoveAt(intptr_t offset) {
+ ASSERT(offset < size_);
+
+ size_--;
+
+ if (offset == size_) {
+ RemoveMapEntry(min_heap_[offset].value);
+ } else {
+ Replace(offset, size_);
+ BubbleDown(offset);
+ }
+
+ if (size_ <= (min_heap_size_ >> 2) &&
+ kMinimumSize <= (min_heap_size_ >> 1)) {
+ Resize(min_heap_size_ >> 1);
+ }
+ }
+
+ void BubbleUp(intptr_t offset) {
+ while (true) {
+ if (offset == 0) return;
+
+ intptr_t parent = (offset - 1) / 2;
+ if (min_heap_[parent].priority > min_heap_[offset].priority) {
+ Swap(parent, offset);
+ }
+ offset = parent;
+ }
+ }
+
+ void BubbleDown(intptr_t offset) {
+ while (true) {
+ intptr_t left_child_index = 2 * offset + 1;
+ bool has_left_child = left_child_index < size_;
+
+ if (!has_left_child) return;
+
+ intptr_t smallest_index = offset;
+
+ if (min_heap_[left_child_index].priority < min_heap_[offset].priority) {
+ smallest_index = left_child_index;
+ }
+
+ intptr_t right_child_index = left_child_index + 1;
+ bool has_right_child = right_child_index < size_;
+ if (has_right_child) {
+ if (min_heap_[right_child_index].priority <
+ min_heap_[smallest_index].priority) {
+ smallest_index = right_child_index;
+ }
+ }
+
+ if (offset == smallest_index) {
+ return;
+ }
+
+ Swap(offset, smallest_index);
+ offset = smallest_index;
+ }
+ }
+
+ void Set(intptr_t offset1, const Entry& entry) {
+ min_heap_[offset1] = entry;
+ SetMapEntry(entry.value, offset1);
+ }
+
+ void Swap(intptr_t offset1, intptr_t offset2) {
+ Entry temp = min_heap_[offset1];
+ min_heap_[offset1] = min_heap_[offset2];
+ min_heap_[offset2] = temp;
+
+ SetMapEntry(min_heap_[offset1].value, offset1);
+ SetMapEntry(min_heap_[offset2].value, offset2);
+ }
+
+ void Replace(intptr_t index, intptr_t with_other) {
+ RemoveMapEntry(min_heap_[index].value);
+
+ const Entry& entry = min_heap_[with_other];
+ SetMapEntry(entry.value, index);
+ min_heap_[index] = entry;
+ }
+
+ void Resize(intptr_t new_min_heap_size) {
+ ASSERT(size_ < new_min_heap_size);
+ ASSERT(new_min_heap_size != min_heap_size_);
+
+ Entry* new_backing = reinterpret_cast<Entry*>(
+ realloc(min_heap_, sizeof(Entry) * new_min_heap_size));
+
+ if (new_backing == NULL) FATAL("Cannot allocate memory.");
+
+ min_heap_ = new_backing;
+ min_heap_size_ = new_min_heap_size;
+ }
+
+ // The array is representing a tree structure with guaranteed log(n) height.
+ // It has the property that the value of node N is always equal or smaller
+ // than the value of N's children. Furthermore it is a "dense" tree in the
+ // sense that all rows/layers of the tree are fully occupied except the last
+ // one. The way to represent such "dense" trees is via an array that allows
+ // finding left/right children by <2*index+1><2*index+2> and the parent by
+ // <(index-1)/2>.
+ //
+ // Insertion operations can be performed by adding one more entry at the end
+ // (bottom right) and bubbling it up until the tree invariant is satisfied
+ // again.
+ //
+ // Deletion operations can be performed by replacing the minimum element
+ // (first entry) by the last entry (bottom right) and bubbling it down until
+ // the tree invariant is satisified again.
+ Entry* min_heap_;
+ intptr_t min_heap_size_;
+ intptr_t size_;
+ SimpleHashMap hashmap_;
+};
+
+} // namespace dart
+
+#endif // RUNTIME_PLATFORM_PRIORITY_QUEUE_H_
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 031ab05..2b2ab85 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -340,9 +340,7 @@
}
}
- void WriteTokenPosition(TokenPosition pos) {
- Write<int32_t>(pos.SnapshotEncode());
- }
+ void WriteTokenPosition(TokenPosition pos) { Write(pos.Serialize()); }
void WriteCid(intptr_t cid) {
COMPILE_ASSERT(ObjectLayout::kClassIdTagSize <= 32);
@@ -616,7 +614,7 @@
}
TokenPosition ReadTokenPosition() {
- return TokenPosition::SnapshotDecode(Read<int32_t>());
+ return TokenPosition::Deserialize(Read<int32_t>());
}
intptr_t ReadCid() {
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index edce815..e75d702 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -40,10 +40,11 @@
prev_pc_offset = pc_offset;
if (!FLAG_precompiled_mode) {
+ const int32_t encoded_pos = token_pos.Serialize();
encoded_data_.WriteSLEB128(deopt_id - prev_deopt_id);
- encoded_data_.WriteSLEB128(token_pos.value() - prev_token_pos);
+ encoded_data_.WriteSLEB128(encoded_pos - prev_token_pos);
prev_deopt_id = deopt_id;
- prev_token_pos = token_pos.value();
+ prev_token_pos = encoded_pos;
}
}
}
@@ -197,8 +198,8 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-const TokenPosition CodeSourceMapBuilder::kInitialPosition =
- TokenPosition(TokenPosition::kDartCodeProloguePos);
+const TokenPosition& CodeSourceMapBuilder::kInitialPosition =
+ TokenPosition::kDartCodePrologue;
CodeSourceMapBuilder::CodeSourceMapBuilder(
Zone* zone,
@@ -311,7 +312,7 @@
}
for (intptr_t i = to_push.length() - 1; i >= 0; i--) {
intptr_t callee_id = to_push[i];
- TokenPosition call_token;
+ TokenPosition call_token = TokenPosition::kNoSource;
if (callee_id != 0) {
// TODO(rmacnak): Should make this array line up with the others.
call_token = inline_id_to_token_pos_[callee_id - 1];
@@ -396,20 +397,19 @@
void CodeSourceMapBuilder::WriteChangePosition(TokenPosition pos) {
stream_.Write<uint8_t>(kChangePosition);
- intptr_t position_or_line = pos.value();
+ intptr_t position_or_line = pos.Serialize();
#if defined(DART_PRECOMPILER)
- intptr_t column = TokenPosition::kNoSourcePos;
+ intptr_t column = TokenPosition::kNoSource.Serialize();
if (FLAG_precompiled_mode) {
// Don't use the raw position value directly in precompiled mode. Instead,
// use the value of kNoSource as a fallback when no line or column
// information is found.
- position_or_line = TokenPosition::kNoSourcePos;
+ position_or_line = TokenPosition::kNoSource.Serialize();
intptr_t inline_id = buffered_inline_id_stack_.Last();
if (inline_id < inline_id_to_function_.length()) {
const Function* function = inline_id_to_function_[inline_id];
Script& script = Script::Handle(function->script());
- script.GetTokenLocationUsingLineStarts(pos.SourcePosition(),
- &position_or_line, &column);
+ script.GetTokenLocation(pos, &position_or_line, &column);
}
}
#endif
@@ -619,8 +619,8 @@
THR_Print("%" Px "-%" Px ": ", start + current_pc_offset,
start + current_pc_offset + delta - 1);
for (intptr_t i = 0; i < function_stack.length(); i++) {
- THR_Print("%s@%" Pd " ", function_stack[i]->ToCString(),
- token_positions[i].value());
+ THR_Print("%s@%s", function_stack[i]->ToCString(),
+ token_positions[i].ToCString());
}
THR_Print("\n");
current_pc_offset += delta;
@@ -698,7 +698,8 @@
}
TokenPosition CodeSourceMapReader::ReadPosition(ReadStream* stream) {
- const intptr_t line = stream->Read<int32_t>();
+ const TokenPosition line =
+ TokenPosition::Deserialize(stream->Read<int32_t>());
#if defined(DART_PRECOMPILER)
// The special handling for non-symbolic stack trace mode only needs to
// happen in the precompiler, because those CSMs are not serialized in
@@ -707,7 +708,7 @@
stream->Read<int32_t>(); // Discard the column information.
}
#endif
- return TokenPosition(line);
+ return line;
}
} // namespace dart
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index f42190b..bb2f773 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -42,7 +42,7 @@
intptr_t prev_pc_offset;
intptr_t prev_deopt_id;
- intptr_t prev_token_pos;
+ int32_t prev_token_pos;
DISALLOW_COPY_AND_ASSIGN(DescriptorList);
};
@@ -186,7 +186,7 @@
// The position at which a function implicitly starts, for both the root and
// after a push bytecode. We use the classifying position kDartCodePrologue
// since it is the most common.
- static const TokenPosition kInitialPosition;
+ static const TokenPosition& kInitialPosition;
static const uint8_t kChangePosition = 0;
static const uint8_t kAdvancePC = 1;
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index d8e2c41..1f5cb52 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -123,7 +123,7 @@
ISOLATE_UNIT_TEST_CASE(DescriptorList_TokenPositions) {
DescriptorList* descriptors = new DescriptorList(thread->zone());
ASSERT(descriptors != NULL);
- const intptr_t token_positions[] = {
+ const int32_t token_positions[] = {
kMinInt32,
5,
13,
@@ -141,12 +141,12 @@
TokenPosition::kMinSourcePos,
TokenPosition::kMaxSourcePos,
};
- const intptr_t num_token_positions =
- sizeof(token_positions) / sizeof(token_positions[0]);
+ const intptr_t num_token_positions = ARRAY_SIZE(token_positions);
for (intptr_t i = 0; i < num_token_positions; i++) {
- descriptors->AddDescriptor(PcDescriptorsLayout::kRuntimeCall, 0, 0,
- TokenPosition(token_positions[i]), 0, 1);
+ const TokenPosition& tp = TokenPosition::Deserialize(token_positions[i]);
+ descriptors->AddDescriptor(PcDescriptorsLayout::kRuntimeCall, 0, 0, tp, 0,
+ 1);
}
const PcDescriptors& finalized_descriptors =
@@ -158,11 +158,12 @@
intptr_t i = 0;
while (it.MoveNext()) {
- if (token_positions[i] != it.TokenPos().value()) {
- OS::PrintErr("[%" Pd "]: Expected: %" Pd " != %" Pd "\n", i,
- token_positions[i], it.TokenPos().value());
+ const TokenPosition& tp = TokenPosition::Deserialize(token_positions[i]);
+ if (tp != it.TokenPos()) {
+ OS::PrintErr("[%" Pd "]: Expected: %s != %s\n", i, tp.ToCString(),
+ it.TokenPos().ToCString());
}
- EXPECT(token_positions[i] == it.TokenPos().value());
+ EXPECT(tp == it.TokenPos());
i++;
}
}
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index d2f88ed..8b1a53b 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -516,7 +516,7 @@
WriteString(str_);
WriteInt(function.kind());
- WriteInt(function.token_pos().value());
+ WriteInt(function.token_pos().Serialize());
code_ = function.CurrentCode();
intptr_t usage = function.usage_counter();
@@ -814,7 +814,7 @@
func_name_ = ReadString(); // Without private mangling.
FunctionLayout::Kind kind = static_cast<FunctionLayout::Kind>(ReadInt());
- intptr_t token_pos = ReadInt();
+ const TokenPosition& token_pos = TokenPosition::Deserialize(ReadInt());
intptr_t usage = ReadInt();
intptr_t inlining_depth = ReadInt();
intptr_t num_call_sites = ReadInt();
@@ -926,7 +926,7 @@
}
FunctionPtr TypeFeedbackLoader::FindFunction(FunctionLayout::Kind kind,
- intptr_t token_pos) {
+ const TokenPosition& token_pos) {
if (cls_name_.Equals(Symbols::TopLevel())) {
func_ = lib_.LookupFunctionAllowPrivate(func_name_);
} else {
@@ -969,8 +969,7 @@
bool found = false;
for (intptr_t i = 0; i < closure_functions.Length(); i++) {
func_ ^= closure_functions.At(i);
- if ((func_.Owner() == cls_.raw()) &&
- (func_.token_pos().value() == token_pos)) {
+ if (func_.Owner() == cls_.raw() && func_.token_pos() == token_pos) {
found = true;
break;
}
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index 80d671e..459ca27 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -102,7 +102,8 @@
ObjectPtr LoadClasses();
ObjectPtr LoadFields();
ObjectPtr LoadFunction();
- FunctionPtr FindFunction(FunctionLayout::Kind kind, intptr_t token_pos);
+ FunctionPtr FindFunction(FunctionLayout::Kind kind,
+ const TokenPosition& token_pos);
ClassPtr ReadClassByName();
StringPtr ReadString();
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 41a7902..a1da918 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -94,7 +94,7 @@
static inline intptr_t Hashcode(Key key) {
const TokenPosition token_pos = key->token_pos();
if (token_pos.IsReal()) {
- return token_pos.value();
+ return token_pos.Hash();
}
return key->kernel_offset();
}
@@ -117,7 +117,7 @@
static Value ValueOf(Pair kv) { return kv; }
- static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
+ static inline intptr_t Hashcode(Key key) { return key->token_pos().Hash(); }
static inline bool IsKeyEqual(Pair pair, Key key) {
return pair->raw() == key->raw();
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index e7e73a5..8df2bfc 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -339,7 +339,8 @@
THR_Print("%s}\n", handlers.ToCString());
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
- if (code.catch_entry_moves_maps() != Object::null()) {
+ if (FLAG_precompiled_mode &&
+ code.catch_entry_moves_maps() != Object::null()) {
THR_Print("Catch entry moves for function '%s' {\n", function_fullname);
CatchEntryMovesMapReader reader(
TypedData::Handle(code.catch_entry_moves_maps()));
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index 6c30d95..fec331a 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -768,7 +768,7 @@
TokenPosition token_pos = TokenPosition::kNoSource;
if (auto const token_int =
CheckInteger(list->ExtraLookupValue("token_pos"))) {
- token_pos = TokenPosition(token_int->value());
+ token_pos = TokenPosition::Deserialize(token_int->value());
}
InstrInfo common_info = {deopt_id, token_pos};
@@ -1833,7 +1833,7 @@
}
TokenPosition token_pos = TokenPosition::kNoSource;
if (const auto pos_sexp = CheckInteger(list->ExtraLookupValue("token_pos"))) {
- token_pos = TokenPosition(pos_sexp->value());
+ token_pos = TokenPosition::Deserialize(pos_sexp->value());
}
auto type_args_ptr = &Object::null_type_arguments();
if (const auto ta_sexp = list->ExtraLookupValue("type_args")) {
diff --git a/runtime/vm/compiler/backend/il_serializer.cc b/runtime/vm/compiler/backend/il_serializer.cc
index 5e6fc92..979c410 100644
--- a/runtime/vm/compiler/backend/il_serializer.cc
+++ b/runtime/vm/compiler/backend/il_serializer.cc
@@ -437,7 +437,7 @@
AddSymbol(sexp, "Type");
const auto& type = Type::Cast(t);
if (!type.token_pos().IsNoSource()) {
- AddExtraInteger(sexp, "token_pos", type.token_pos().value());
+ AddExtraInteger(sexp, "token_pos", type.token_pos().Serialize());
}
// We want to check for the type being recursive before we may serialize
// any sub-parts that include possible TypeRefs to this type.
@@ -823,7 +823,7 @@
sexp->AddExtra("env", env()->ToSExpression(s));
}
if (!token_pos().IsNoSource()) {
- s->AddExtraInteger(sexp, "token_pos", token_pos().value());
+ s->AddExtraInteger(sexp, "token_pos", token_pos().Serialize());
}
}
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 269a793..c682aef 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -1692,9 +1692,7 @@
// For now, bail out for large functions to avoid OOM situations.
// TODO(fschneider): Fix the memory consumption issue.
- intptr_t function_length = graph->function().end_token_pos().Pos() -
- graph->function().token_pos().Pos();
- if (function_length >= FLAG_huge_method_cutoff_in_tokens) {
+ if (graph->function().SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
return false;
}
@@ -2850,9 +2848,7 @@
// For now, bail out for large functions to avoid OOM situations.
// TODO(fschneider): Fix the memory consumption issue.
- intptr_t function_length = graph->function().end_token_pos().Pos() -
- graph->function().token_pos().Pos();
- if (function_length >= FLAG_huge_method_cutoff_in_tokens) {
+ if (graph->function().SourceSize() >= FLAG_huge_method_cutoff_in_tokens) {
return;
}
diff --git a/runtime/vm/compiler/backend/yield_position_test.cc b/runtime/vm/compiler/backend/yield_position_test.cc
index a32bb74..e90be85 100644
--- a/runtime/vm/compiler/backend/yield_position_test.cc
+++ b/runtime/vm/compiler/backend/yield_position_test.cc
@@ -103,11 +103,11 @@
EXPECT_EQ(3, yield_points.length());
EXPECT_EQ(1, yield_points[0].first);
- EXPECT_EQ(88, yield_points[0].second.value());
+ EXPECT_EQ(88, yield_points[0].second.Pos());
EXPECT_EQ(2, yield_points[1].first);
- EXPECT_EQ(129, yield_points[1].second.value());
+ EXPECT_EQ(129, yield_points[1].second.Pos());
EXPECT_EQ(3, yield_points[2].first);
- EXPECT_EQ(170, yield_points[2].second.value());
+ EXPECT_EQ(170, yield_points[2].second.Pos());
};
validate_indices(*GetYieldPointsFromGraph(flow_graph));
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 7b3e6a0..7378aa7 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -4839,8 +4839,9 @@
// Use position of equal sign if it exists. If the equal sign does not exist
// use the position of the identifier.
- TokenPosition debug_position =
- Utils::Maximum(helper.position_, helper.equals_position_);
+ const TokenPosition debug_position = helper.equals_position_.IsReal()
+ ? helper.equals_position_
+ : helper.position_;
if (NeedsDebugStepCheck(stack(), debug_position)) {
instructions = DebugStepCheck(debug_position) + instructions;
}
@@ -4882,7 +4883,7 @@
// Positions has to be unique in regards to the parent.
// A non-real at this point is probably -1, we cannot blindly use that
// as others might use it too. Create a new dummy non-real TokenPosition.
- position = TokenPosition(offset).ToSynthetic();
+ position = TokenPosition::Synthetic(offset);
}
// The VM has a per-isolate table of functions indexed by the enclosing
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 36c8a5e..72b3106 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -296,8 +296,8 @@
void SetNext(Field field) { next_read_ = field; }
void SetJustRead(Field field) { next_read_ = field + 1; }
- TokenPosition position_;
- TokenPosition end_position_;
+ TokenPosition position_ = TokenPosition::kNoSource;
+ TokenPosition end_position_ = TokenPosition::kNoSource;
AsyncMarker async_marker_;
AsyncMarker dart_async_marker_;
intptr_t total_parameter_count_ = 0;
@@ -352,7 +352,7 @@
return (flags_ & kIsGenericCovariantImpl) != 0;
}
- TokenPosition position_;
+ TokenPosition position_ = TokenPosition::kNoSource;
uint8_t flags_ = 0;
StringIndex name_index_;
@@ -415,8 +415,8 @@
return (flags_ & kIsGenericCovariantImpl) != 0;
}
- TokenPosition position_;
- TokenPosition equals_position_;
+ TokenPosition position_ = TokenPosition::kNoSource;
+ TokenPosition equals_position_ = TokenPosition::kNoSource;
uint8_t flags_ = 0;
StringIndex name_index_;
intptr_t annotation_count_ = 0;
@@ -488,8 +488,8 @@
NameIndex canonical_name_getter_;
NameIndex canonical_name_setter_;
- TokenPosition position_;
- TokenPosition end_position_;
+ TokenPosition position_ = TokenPosition::kNoSource;
+ TokenPosition end_position_ = TokenPosition::kNoSource;
uint32_t flags_ = 0;
intptr_t source_uri_index_ = 0;
intptr_t annotation_count_ = 0;
@@ -589,9 +589,9 @@
}
NameIndex canonical_name_;
- TokenPosition start_position_;
- TokenPosition position_;
- TokenPosition end_position_;
+ TokenPosition start_position_ = TokenPosition::kNoSource;
+ TokenPosition position_ = TokenPosition::kNoSource;
+ TokenPosition end_position_ = TokenPosition::kNoSource;
Kind kind_;
uint32_t flags_ = 0;
intptr_t source_uri_index_ = 0;
@@ -655,9 +655,9 @@
bool IsSynthetic() { return (flags_ & kSynthetic) != 0; }
NameIndex canonical_name_;
- TokenPosition start_position_;
- TokenPosition position_;
- TokenPosition end_position_;
+ TokenPosition start_position_ = TokenPosition::kNoSource;
+ TokenPosition position_ = TokenPosition::kNoSource;
+ TokenPosition end_position_ = TokenPosition::kNoSource;
uint8_t flags_ = 0;
intptr_t source_uri_index_ = 0;
intptr_t annotation_count_ = 0;
@@ -733,9 +733,9 @@
}
NameIndex canonical_name_;
- TokenPosition start_position_;
- TokenPosition position_;
- TokenPosition end_position_;
+ TokenPosition start_position_ = TokenPosition::kNoSource;
+ TokenPosition position_ = TokenPosition::kNoSource;
+ TokenPosition end_position_ = TokenPosition::kNoSource;
StringIndex name_index_;
intptr_t source_uri_index_ = 0;
intptr_t annotation_count_ = 0;
diff --git a/runtime/vm/compiler/frontend/scope_builder.h b/runtime/vm/compiler/frontend/scope_builder.h
index c8680c3..1531508 100644
--- a/runtime/vm/compiler/frontend/scope_builder.h
+++ b/runtime/vm/compiler/frontend/scope_builder.h
@@ -162,7 +162,7 @@
intptr_t name_index_;
bool needs_expr_temp_;
- TokenPosition first_body_token_position_;
+ TokenPosition first_body_token_position_ = TokenPosition::kNoSource;
KernelReaderHelper helper_;
ConstantReader constant_reader_;
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index d88ab4d..37606511 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -724,8 +724,7 @@
ParsedFunction* parsed_function = new (zone)
ParsedFunction(thread, Function::ZoneHandle(zone, function.raw()));
if (trace_compiler) {
- const intptr_t token_size =
- function.end_token_pos().Pos() - function.token_pos().Pos();
+ const intptr_t token_size = function.SourceSize();
THR_Print("Compiling %s%sfunction %s: '%s' @ token %s, size %" Pd "\n",
(osr_id == Compiler::kNoOSRDeoptId ? "" : "osr "),
(optimized ? "optimized " : ""),
@@ -1300,9 +1299,9 @@
DEFINE_RUNTIME_ENTRY(CompileFunction, 1) {
const Function& function = Function::CheckedHandle(zone, arguments.ArgAt(0));
- FATAL3("Precompilation missed function %s (%" Pd ", %s)\n",
+ FATAL3("Precompilation missed function %s (%s, %s)\n",
function.ToLibNamePrefixedQualifiedCString(),
- function.token_pos().value(),
+ function.token_pos().ToCString(),
Function::KindToCString(function.kind()));
}
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index d1096d7..6120b67 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -109,8 +109,7 @@
TokenPosition token_pos) {
ASSERT(!IsLatent());
ASSERT(func.script() == script_);
- ASSERT((func.token_pos() <= token_pos) &&
- (token_pos <= func.end_token_pos()));
+ ASSERT(token_pos.IsWithin(func.token_pos(), func.end_token_pos()));
ASSERT(func.is_debuggable());
function_ = func.raw();
token_pos_ = token_pos;
@@ -394,11 +393,10 @@
const Script& script,
TokenPosition token_pos,
TokenPosition end_token_pos) {
- TokenPosition func_start = func.token_pos();
- if (((func_start <= token_pos) && (token_pos <= func.end_token_pos())) ||
- ((token_pos <= func_start) && (func_start <= end_token_pos))) {
- // Check script equality second because it allocates
- // handles as a side effect.
+ const TokenPosition& func_start = func.token_pos();
+ if (token_pos.IsWithin(func_start, func.end_token_pos()) ||
+ func_start.IsWithin(token_pos, end_token_pos)) {
+ // Check script equality last because it allocates handles as a side effect.
return func.script() == script.raw();
}
return false;
@@ -566,24 +564,20 @@
intptr_t ActivationFrame::LineNumber() {
// Compute line number lazily since it causes scanning of the script.
- if ((line_number_ < 0) && TokenPos().IsSourcePosition()) {
- const TokenPosition token_pos = TokenPos().SourcePosition();
+ const TokenPosition& token_pos = TokenPos();
+ if ((line_number_ < 0) && token_pos.IsReal()) {
const Script& script = Script::Handle(SourceScript());
- script.GetTokenLocation(token_pos, &line_number_, NULL);
+ script.GetTokenLocation(token_pos, &line_number_, nullptr);
}
return line_number_;
}
intptr_t ActivationFrame::ColumnNumber() {
// Compute column number lazily since it causes scanning of the script.
- if ((column_number_ < 0) && TokenPos().IsSourcePosition()) {
- const TokenPosition token_pos = TokenPos().SourcePosition();
+ const TokenPosition& token_pos = TokenPos();
+ if ((column_number_ < 0) && token_pos.IsReal()) {
const Script& script = Script::Handle(SourceScript());
- if (script.HasSource()) {
- script.GetTokenLocation(token_pos, &line_number_, &column_number_);
- } else {
- column_number_ = -1;
- }
+ script.GetTokenLocation(token_pos, &line_number_, &column_number_);
}
return column_number_;
}
@@ -648,13 +642,14 @@
}
intptr_t var_desc_len = var_descriptors_.Length();
bool found = false;
+ // We store the deopt ids as real token positions.
+ const auto to_compare = TokenPosition::Deserialize(deopt_id);
for (intptr_t cur_idx = 0; cur_idx < var_desc_len; cur_idx++) {
LocalVarDescriptorsLayout::VarInfo var_info;
var_descriptors_.GetInfo(cur_idx, &var_info);
const int8_t kind = var_info.kind();
if ((kind == LocalVarDescriptorsLayout::kContextLevel) &&
- (deopt_id >= var_info.begin_pos.value()) &&
- (deopt_id <= var_info.end_pos.value())) {
+ to_compare.IsWithin(var_info.begin_pos, var_info.end_pos)) {
context_level_ = var_info.index();
found = true;
break;
@@ -925,51 +920,51 @@
(kind != LocalVarDescriptorsLayout::kContextVar)) {
continue;
}
- if ((var_info.begin_pos <= activation_token_pos) &&
- (activation_token_pos <= var_info.end_pos)) {
- if ((kind == LocalVarDescriptorsLayout::kContextVar) &&
- (ContextLevel() < var_info.scope_id)) {
- // The variable is textually in scope but the context level
- // at the activation frame's PC is lower than the context
- // level of the variable. The context containing the variable
- // has already been removed from the chain. This can happen when we
- // break at a return statement, since the contexts get discarded
- // before the debugger gets called.
- continue;
- }
- // The current variable is textually in scope. Now check whether
- // there is another local variable with the same name that shadows
- // or is shadowed by this variable.
- String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
- intptr_t indices_len = desc_indices_.length();
- bool name_match_found = false;
- for (intptr_t i = 0; i < indices_len; i++) {
- if (var_name.Equals(*var_names[i])) {
- // Found two local variables with the same name. Now determine
- // which one is shadowed.
- name_match_found = true;
- LocalVarDescriptorsLayout::VarInfo i_var_info;
- var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
- if (i_var_info.begin_pos < var_info.begin_pos) {
- // The variable we found earlier is in an outer scope
- // and is shadowed by the current variable. Replace the
- // descriptor index of the previously found variable
- // with the descriptor index of the current variable.
- desc_indices_[i] = cur_idx;
- } else {
- // The variable we found earlier is in an inner scope
- // and shadows the current variable. Skip the current
- // variable. (Nothing to do.)
- }
- break; // Stop looking for name matches.
+ if (!activation_token_pos.IsWithin(var_info.begin_pos, var_info.end_pos)) {
+ continue;
+ }
+ if ((kind == LocalVarDescriptorsLayout::kContextVar) &&
+ (ContextLevel() < var_info.scope_id)) {
+ // The variable is textually in scope but the context level
+ // at the activation frame's PC is lower than the context
+ // level of the variable. The context containing the variable
+ // has already been removed from the chain. This can happen when we
+ // break at a return statement, since the contexts get discarded
+ // before the debugger gets called.
+ continue;
+ }
+ // The current variable is textually in scope. Now check whether
+ // there is another local variable with the same name that shadows
+ // or is shadowed by this variable.
+ String& var_name = String::Handle(var_descriptors_.GetName(cur_idx));
+ intptr_t indices_len = desc_indices_.length();
+ bool name_match_found = false;
+ for (intptr_t i = 0; i < indices_len; i++) {
+ if (var_name.Equals(*var_names[i])) {
+ // Found two local variables with the same name. Now determine
+ // which one is shadowed.
+ name_match_found = true;
+ LocalVarDescriptorsLayout::VarInfo i_var_info;
+ var_descriptors_.GetInfo(desc_indices_[i], &i_var_info);
+ if (i_var_info.begin_pos < var_info.begin_pos) {
+ // The variable we found earlier is in an outer scope
+ // and is shadowed by the current variable. Replace the
+ // descriptor index of the previously found variable
+ // with the descriptor index of the current variable.
+ desc_indices_[i] = cur_idx;
+ } else {
+ // The variable we found earlier is in an inner scope
+ // and shadows the current variable. Skip the current
+ // variable. (Nothing to do.)
}
+ break; // Stop looking for name matches.
}
- if (!name_match_found) {
- // No duplicate name found. Add the current descriptor index to the
- // list of visible variables.
- desc_indices_.Add(cur_idx);
- var_names.Add(&var_name);
- }
+ }
+ if (!name_match_found) {
+ // No duplicate name found. Add the current descriptor index to the
+ // list of visible variables.
+ desc_indices_.Add(cur_idx);
+ var_names.Add(&var_name);
}
}
vars_initialized_ = true;
@@ -1167,7 +1162,7 @@
Object& value = Instance::Handle();
const Array& list = Array::Handle(Array::New(2 * num_variables));
for (intptr_t i = 0; i < num_variables; i++) {
- TokenPosition ignore;
+ TokenPosition ignore = TokenPosition::kNoSource;
VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
list.SetAt(2 * i, var_name);
list.SetAt((2 * i) + 1, value);
@@ -1181,7 +1176,7 @@
String& var_name = String::Handle();
Instance& value = Instance::Handle();
for (intptr_t i = 0; i < num_variables; i++) {
- TokenPosition ignore;
+ TokenPosition ignore = TokenPosition::kNoSource;
VariableAt(i, &var_name, &ignore, &ignore, &ignore, &value);
if (var_name.Equals(Symbols::This())) {
return value.raw();
@@ -1232,7 +1227,7 @@
TypeArguments& type_arguments = TypeArguments::Handle();
intptr_t num_variables = desc_indices_.length();
for (intptr_t i = 0; i < num_variables; i++) {
- TokenPosition ignore;
+ TokenPosition ignore = TokenPosition::kNoSource;
VariableAt(i, &name, &ignore, &ignore, &ignore, &value);
if (name.Equals(Symbols::FunctionTypeArgumentsVar())) {
type_arguments_available = true;
@@ -1347,7 +1342,7 @@
const Script& script = Script::Handle(SourceScript());
jsobj->AddProperty("type", "Frame");
jsobj->AddProperty("kind", KindToCString(kind_));
- const TokenPosition pos = TokenPos().SourcePosition();
+ const TokenPosition& pos = TokenPos();
jsobj->AddLocation(script, pos);
jsobj->AddProperty("function", function());
jsobj->AddProperty("code", code());
@@ -1357,9 +1352,9 @@
for (intptr_t v = 0; v < num_vars; v++) {
String& var_name = String::Handle();
Instance& var_value = Instance::Handle();
- TokenPosition declaration_token_pos;
- TokenPosition visible_start_token_pos;
- TokenPosition visible_end_token_pos;
+ TokenPosition declaration_token_pos = TokenPosition::kNoSource;
+ TokenPosition visible_start_token_pos = TokenPosition::kNoSource;
+ TokenPosition visible_end_token_pos = TokenPosition::kNoSource;
VariableAt(v, &var_name, &declaration_token_pos, &visible_start_token_pos,
&visible_end_token_pos, &var_value);
if (!IsSyntheticVariableName(var_name)) {
@@ -1383,7 +1378,7 @@
jsobj->AddProperty("type", "Frame");
jsobj->AddProperty("kind", KindToCString(kind_));
const Script& script = Script::Handle(SourceScript());
- const TokenPosition pos = TokenPos().SourcePosition();
+ const TokenPosition& pos = TokenPos();
jsobj->AddLocation(script, pos);
jsobj->AddProperty("function", function());
jsobj->AddProperty("code", code());
@@ -2239,16 +2234,14 @@
intptr_t token_start_column = -1;
intptr_t token_line = -1;
if (requested_column >= 0) {
- TokenPosition ignored;
- TokenPosition end_of_line_pos;
+ TokenPosition ignored = TokenPosition::kNoSource;
+ TokenPosition end_of_line_pos = TokenPosition::kNoSource;
script.GetTokenLocation(pos, &token_line, &token_start_column);
script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
TokenPosition token_end_pos =
- (end_of_line_pos < next_closest_token_position)
- ? end_of_line_pos
- : next_closest_token_position;
+ TokenPosition::Min(next_closest_token_position, end_of_line_pos);
- if ((token_end_pos < exact_token_pos) ||
+ if ((exact_token_pos.IsReal() && (token_end_pos < exact_token_pos)) ||
(token_start_column > *best_column)) {
// Prefer the token with the lowest column number compatible
// with the requested column.
@@ -2261,9 +2254,11 @@
*best_fit_pos = pos;
*best_line = token_line;
*best_column = token_start_column;
- // best_token_pos is only used when column number is specified.
- *best_token_pos = TokenPosition(exact_token_pos.value() -
- (requested_column - *best_column));
+ // best_token_pos should only be real when the column number is specified.
+ if (requested_column >= 0 && exact_token_pos.IsReal()) {
+ *best_token_pos = TokenPosition::Deserialize(
+ exact_token_pos.Pos() - (requested_column - *best_column));
+ }
}
}
@@ -2330,12 +2325,9 @@
TokenPosition exact_token_pos) {
ASSERT(!func.HasOptimizedCode());
- if (requested_token_pos < func.token_pos()) {
- requested_token_pos = func.token_pos();
- }
- if (last_token_pos > func.end_token_pos()) {
- last_token_pos = func.end_token_pos();
- }
+ requested_token_pos =
+ TokenPosition::Max(requested_token_pos, func.token_pos());
+ last_token_pos = TokenPosition::Min(last_token_pos, func.end_token_pos());
Zone* zone = Thread::Current()->zone();
Script& script = Script::Handle(zone, func.script());
@@ -2351,15 +2343,19 @@
TokenPosition best_fit_pos = TokenPosition::kMaxSource;
intptr_t best_column = INT_MAX;
intptr_t best_line = INT_MAX;
- // best_token_pos and exact_token_pos are only used
- // if column number is provided.
+ // best_token_pos is only set to a real position if a real exact_token_pos
+ // and a column number are provided.
TokenPosition best_token_pos = TokenPosition::kNoSource;
PcDescriptors::Iterator iter(desc, kSafepointKind);
while (iter.MoveNext()) {
- const TokenPosition pos = iter.TokenPos();
- if ((!pos.IsReal()) || (pos < requested_token_pos) ||
- (pos > last_token_pos)) {
+ const TokenPosition& pos = iter.TokenPos();
+ if (pos.IsSynthetic() && pos == requested_token_pos) {
+ // if there's a safepoint for a synthetic function start and the start
+ // was requested, we're done.
+ return pos;
+ }
+ if (!pos.IsWithin(requested_token_pos, last_token_pos)) {
// Token is not in the target range.
continue;
}
@@ -2368,8 +2364,9 @@
// Find next closest safepoint
PcDescriptors::Iterator iter2(desc, kSafepointKind);
while (iter2.MoveNext()) {
- const TokenPosition next = iter2.TokenPos();
- if (next < next_closest_token_position && next > pos) {
+ const TokenPosition& next = iter2.TokenPos();
+ if (!next.IsReal()) continue;
+ if ((pos < next) && (next < next_closest_token_position)) {
next_closest_token_position = next;
}
}
@@ -2384,33 +2381,31 @@
// the token on the line which is at the best fit column (if column
// was specified) and has the lowest code address.
if (best_fit_pos != TokenPosition::kMaxSource) {
+ ASSERT(best_fit_pos.IsReal());
const Script& script = Script::Handle(zone, func.script());
const TokenPosition begin_pos = best_fit_pos;
- TokenPosition end_of_line_pos;
+ TokenPosition end_of_line_pos = TokenPosition::kNoSource;
if (best_line == -1) {
- script.GetTokenLocation(begin_pos, &best_line, NULL);
+ script.GetTokenLocation(begin_pos, &best_line, nullptr);
}
ASSERT(best_line > 0);
- TokenPosition ignored;
+ TokenPosition ignored = TokenPosition::kNoSource;
script.TokenRangeAtLine(best_line, &ignored, &end_of_line_pos);
- if (end_of_line_pos < begin_pos) {
- end_of_line_pos = begin_pos;
- }
+ end_of_line_pos = TokenPosition::Max(end_of_line_pos, begin_pos);
uword lowest_pc_offset = kUwordMax;
PcDescriptors::Iterator iter(desc, kSafepointKind);
while (iter.MoveNext()) {
- const TokenPosition pos = iter.TokenPos();
- if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
- // Token is not on same line as best fit.
- continue;
- }
-
- if (requested_column >= 0) {
+ const TokenPosition& pos = iter.TokenPos();
+ if (best_token_pos.IsReal()) {
if (pos != best_token_pos) {
+ // Not an match for the requested column.
continue;
}
+ } else if (!pos.IsWithin(begin_pos, end_of_line_pos)) {
+ // Token is not on same line as best fit.
+ continue;
}
// Prefer the lowest pc offset.
@@ -2557,14 +2552,14 @@
}
}
-static void SelectBestFit(Function* best_fit, Function* func) {
+static void UpdateBestFit(Function* best_fit, const Function& func) {
if (best_fit->IsNull()) {
- *best_fit = func->raw();
- } else {
- if ((func->token_pos() > best_fit->token_pos()) &&
- ((func->end_token_pos() <= best_fit->end_token_pos()))) {
- *best_fit = func->raw();
- }
+ *best_fit = func.raw();
+ } else if ((best_fit->token_pos().IsSynthetic() ||
+ func.token_pos().IsSynthetic() ||
+ (best_fit->token_pos() < func.token_pos())) &&
+ (func.end_token_pos() <= best_fit->end_token_pos())) {
+ *best_fit = func.raw();
}
}
@@ -2623,7 +2618,7 @@
function ^= closures.At(i);
if (FunctionOverlaps(function, script, token_pos, last_token_pos)) {
// Select the inner most closure.
- SelectBestFit(best_fit, &function);
+ UpdateBestFit(best_fit, function);
}
}
if (!best_fit->IsNull()) {
@@ -2688,8 +2683,8 @@
if (!fields.IsNull()) {
const intptr_t num_fields = fields.Length();
for (intptr_t pos = 0; pos < num_fields; pos++) {
- TokenPosition start;
- TokenPosition end;
+ TokenPosition start = TokenPosition::kNoSource;
+ TokenPosition end = TokenPosition::kNoSource;
field ^= fields.At(pos);
ASSERT(!field.IsNull());
if (field.Script() != script.raw()) {
@@ -2702,8 +2697,8 @@
}
start = field.token_pos();
end = field.end_token_pos();
- if ((start <= token_pos && token_pos <= end) ||
- (token_pos <= start && start <= last_token_pos)) {
+ if (token_pos.IsWithin(start, end) ||
+ start.IsWithin(token_pos, last_token_pos)) {
return true;
}
}
@@ -2803,7 +2798,7 @@
// have already been compiled. We can resolve the breakpoint now.
// If requested_column is larger than zero, [token_pos, last_token_pos]
// governs one single line of code.
- TokenPosition exact_token_pos = TokenPosition(-1);
+ TokenPosition exact_token_pos = TokenPosition::kNoSource;
if (token_pos != last_token_pos && requested_column >= 0) {
#if !defined(DART_PRECOMPILED_RUNTIME)
exact_token_pos =
@@ -3010,7 +3005,8 @@
}
return latent_bpt;
}
- TokenPosition first_token_idx, last_token_idx;
+ TokenPosition first_token_idx = TokenPosition::kNoSource;
+ TokenPosition last_token_idx = TokenPosition::kNoSource;
script.TokenRangeAtLine(line_number, &first_token_idx, &last_token_idx);
if (!first_token_idx.IsReal()) {
// Script does not contain the given line number.
@@ -3825,6 +3821,8 @@
// the given token position.
FunctionPtr Debugger::FindInnermostClosure(const Function& function,
TokenPosition token_pos) {
+ ASSERT(function.end_token_pos().IsReal());
+ const TokenPosition& func_start = function.token_pos();
Zone* zone = Thread::Current()->zone();
const Script& outer_origin = Script::Handle(zone, function.script());
const GrowableObjectArray& closures = GrowableObjectArray::Handle(
@@ -3834,12 +3832,16 @@
Function& best_fit = Function::Handle(zone);
for (intptr_t i = 0; i < num_closures; i++) {
closure ^= closures.At(i);
- if ((function.token_pos() < closure.token_pos()) &&
- (closure.end_token_pos() < function.end_token_pos()) &&
- (closure.token_pos() <= token_pos) &&
- (token_pos <= closure.end_token_pos()) &&
+ const TokenPosition& closure_start = closure.token_pos();
+ const TokenPosition& closure_end = closure.end_token_pos();
+ // We're only interested in closures that have real ending token positions.
+ // The starting token position can be synthetic.
+ if (closure_end.IsReal() && (function.end_token_pos() > closure_end) &&
+ (!closure_start.IsReal() || !func_start.IsReal() ||
+ (closure_start > func_start)) &&
+ token_pos.IsWithin(closure_start, closure_end) &&
(closure.script() == outer_origin.raw())) {
- SelectBestFit(&best_fit, &closure);
+ UpdateBestFit(&best_fit, closure);
}
}
return best_fit.raw();
@@ -3851,13 +3853,14 @@
TokenPosition Debugger::FindExactTokenPosition(const Script& script,
TokenPosition start_of_line,
intptr_t column_number) {
- intptr_t line = -1;
- intptr_t col = -1;
- Zone* zone = Thread::Current()->zone();
- kernel::KernelLineStartsReader line_starts_reader(
- TypedData::Handle(zone, script.line_starts()), zone);
- line_starts_reader.LocationForPosition(start_of_line.value(), &line, &col);
- return TokenPosition(start_of_line.value() + (column_number - col));
+ intptr_t line;
+ intptr_t col;
+ script.GetTokenLocation(start_of_line, &line, &col);
+ if (line < 0) {
+ return TokenPosition::kNoSource;
+ }
+ return TokenPosition::Deserialize(start_of_line.Pos() +
+ (column_number - col));
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -3988,7 +3991,8 @@
intptr_t line_number = matched_loc->requested_line_number();
intptr_t column_number = matched_loc->requested_column_number();
ASSERT(line_number >= 0);
- TokenPosition first_token_pos, last_token_pos;
+ TokenPosition first_token_pos = TokenPosition::kNoSource;
+ TokenPosition last_token_pos = TokenPosition::kNoSource;
script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
if (!first_token_pos.IsDebugPause() || !last_token_pos.IsDebugPause()) {
// Script does not contain the given line number or there are no
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index 22df262..ef72088 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -60,7 +60,7 @@
static Value ValueOf(Pair kv) { return kv.index_; }
- static inline intptr_t Hashcode(Key key) { return key->token_pos().value(); }
+ static inline intptr_t Hashcode(Key key) { return key->token_pos().Hash(); }
static inline bool IsKeyEqual(Pair pair, Key key) {
return pair.function_->raw() == key->raw();
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index adfc624..5b3c8fe 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -320,7 +320,7 @@
void JSONStream::PrintValue(TokenPosition tp) {
PrintCommaIfNeeded();
- PrintValue(tp.value());
+ PrintValue(static_cast<intptr_t>(tp.Serialize()));
}
void JSONStream::PrintValue(const ServiceEvent* event) {
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index ed49742..4a65c47 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -78,11 +78,11 @@
for (intptr_t i = 0; i < line_number; ++i) {
cumulative += helper_->At(line_starts_data_, i);
}
- *first_token_index = dart::TokenPosition(cumulative);
+ *first_token_index = dart::TokenPosition::Deserialize(cumulative);
if (line_number == line_starts_data_.Length()) {
- *last_token_index = dart::TokenPosition(source_length);
+ *last_token_index = dart::TokenPosition::Deserialize(source_length);
} else {
- *last_token_index = dart::TokenPosition(
+ *last_token_index = dart::TokenPosition::Deserialize(
cumulative + helper_->At(line_starts_data_, line_number) - 1);
}
}
@@ -168,7 +168,7 @@
void KernelTokenPositionCollector::RecordTokenPosition(TokenPosition position) {
if (record_for_script_id_ == current_script_id_ &&
record_token_positions_into_ != NULL && position.IsReal()) {
- record_token_positions_into_->Add(position.value());
+ record_token_positions_into_->Add(position.Serialize());
}
}
@@ -259,8 +259,8 @@
if (entry.IsClass()) {
const Class& klass = Class::Cast(entry);
if (klass.script() == interesting_script.raw()) {
- token_positions.Add(klass.token_pos().value());
- token_positions.Add(klass.end_token_pos().value());
+ token_positions.Add(klass.token_pos().Serialize());
+ token_positions.Add(klass.end_token_pos().Serialize());
}
if (klass.is_finalized()) {
temp_array = klass.fields();
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 38f1474..48e3231 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -229,14 +229,18 @@
raw_buffer_(buffer),
typed_data_(NULL),
size_(size),
- offset_(0) {}
+ offset_(0),
+ max_position_(TokenPosition::kNoSource),
+ min_position_(TokenPosition::kNoSource) {}
explicit Reader(const ExternalTypedData& typed_data)
: thread_(Thread::Current()),
raw_buffer_(NULL),
typed_data_(&typed_data),
size_(typed_data.IsNull() ? 0 : typed_data.Length()),
- offset_(0) {}
+ offset_(0),
+ max_position_(TokenPosition::kNoSource),
+ min_position_(TokenPosition::kNoSource) {}
uint32_t ReadFromIndex(intptr_t end_offset,
intptr_t fields_before,
@@ -329,14 +333,9 @@
// Position is saved as unsigned,
// but actually ranges from -1 and up (thus the -1)
intptr_t value = ReadUInt() - 1;
- TokenPosition result = TokenPosition(value);
- max_position_ = Utils::Maximum(max_position_, result);
- if (min_position_.IsNoSource()) {
- min_position_ = result;
- } else if (result.IsReal()) {
- min_position_ = Utils::Minimum(min_position_, result);
- }
-
+ TokenPosition result = TokenPosition::Deserialize(value);
+ max_position_ = TokenPosition::Max(max_position_, result);
+ min_position_ = TokenPosition::Min(min_position_, result);
return result;
}
@@ -553,12 +552,8 @@
}
~PositionScope() {
- if (reader_->min_position_.IsNoSource()) {
- reader_->min_position_ = min_;
- } else if (min_.IsReal()) {
- reader_->min_position_ = Utils::Minimum(reader_->min_position_, min_);
- }
- reader_->max_position_ = Utils::Maximum(reader_->max_position_, max_);
+ reader_->min_position_ = TokenPosition::Min(reader_->min_position_, min_);
+ reader_->max_position_ = TokenPosition::Max(reader_->max_position_, max_);
}
private:
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index f2f9877..6cb5b65 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3959,7 +3959,7 @@
const AbstractType& dst_type,
const String& dst_name) {
const Array& args = Array::Handle(Array::New(4));
- const Smi& pos = Smi::Handle(Smi::New(token_pos.value()));
+ const Smi& pos = Smi::Handle(Smi::New(token_pos.Serialize()));
args.SetAt(0, pos);
args.SetAt(1, src_value);
args.SetAt(2, dst_type);
@@ -7640,9 +7640,8 @@
// Native methods don't need to be optimized.
return false;
}
- const intptr_t function_length = end_token_pos().Pos() - token_pos().Pos();
if (is_optimizable() && (script() != Script::null()) &&
- (function_length < FLAG_huge_method_cutoff_in_tokens)) {
+ SourceSize() < FLAG_huge_method_cutoff_in_tokens) {
// Additional check needed for implicit getters.
return (unoptimized_code() == Object::null()) ||
(Code::Handle(unoptimized_code()).Size() <
@@ -9398,7 +9397,7 @@
if (src.IsNull() || src.Length() == 0) {
return Symbols::OptimizedOut().raw();
}
- uint16_t end_char = src.CharAt(end_token_pos().value());
+ uint16_t end_char = src.CharAt(end_token_pos().Pos());
if ((end_char == ',') || // Case 1.
(end_char == ')') || // Case 2.
(end_char == ';' && String::Handle(zone, name())
@@ -9662,6 +9661,27 @@
(NeedsTypeArgumentTypeChecks() || NeedsArgumentTypeChecks());
}
+intptr_t Function::SourceSize() const {
+ const TokenPosition& start = token_pos();
+ const TokenPosition& end = end_token_pos();
+ if (!end.IsReal() || start.IsNoSource() || start.IsClassifying()) {
+ // No source information, so just return 0.
+ return 0;
+ }
+ if (start.IsSynthetic()) {
+ // Try and approximate the source size using the parent's source size.
+ const auto& parent = Function::Handle(parent_function());
+ ASSERT(!parent.IsNull());
+ const intptr_t parent_size = parent.SourceSize();
+ if (parent_size == 0) {
+ return parent_size;
+ }
+ // Parent must have a real ending position.
+ return parent_size - (parent.end_token_pos().Pos() - end.Pos());
+ }
+ return end.Pos() - start.Pos();
+}
+
const char* Function::ToCString() const {
if (IsNull()) {
return "Function: null";
@@ -11231,31 +11251,6 @@
StoreNonPointer(&raw_ptr()->col_offset_, col_offset);
}
-// Specialized for AOT compilation, which does this lookup for every token
-// position that could be part of a stack trace.
-bool Script::GetTokenLocationUsingLineStarts(TokenPosition target_token_pos,
- intptr_t* line,
- intptr_t* column) const {
-#if defined(DART_PRECOMPILED_RUNTIME)
- return false;
-#else
- // Negative positions denote positions that do not correspond to Dart code.
- if (target_token_pos.value() < 0) return false;
-
- Zone* zone = Thread::Current()->zone();
- TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
- ASSERT(!line_starts_data.IsNull());
-
- kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
- line_starts_reader.LocationForPosition(target_token_pos.value(), line,
- column);
- // The line and column numbers returned are ordinals, so we shouldn't get 0.
- ASSERT(*line > 0);
- ASSERT(*column > 0);
- return true;
-#endif
-}
-
#if !defined(DART_PRECOMPILED_RUNTIME)
static bool IsLetter(int32_t c) {
return (('A' <= c) && (c <= 'Z')) || (('a' <= c) && (c <= 'z'));
@@ -11278,37 +11273,36 @@
intptr_t* line,
intptr_t* column,
intptr_t* token_len) const {
- ASSERT(line != NULL);
- Zone* zone = Thread::Current()->zone();
-
- LookupSourceAndLineStarts(zone);
- if (line_starts() == TypedData::null()) {
- // Scripts in the AOT snapshot do not have a line starts array.
- *line = -1;
- if (column != NULL) {
- *column = -1;
- }
- if (token_len != NULL) {
- *token_len = 1;
- }
- return;
+ ASSERT(line != nullptr);
+ // Set up appropriate values for any early returns.
+ *line = -1;
+ if (column != nullptr) {
+ *column = -1;
}
+ if (token_len != nullptr) {
+ *token_len = 1;
+ }
+ // Scripts in the AOT snapshot do not have a line starts array.
#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (!token_pos.IsReal()) return;
+
+ auto const zone = Thread::Current()->zone();
+ LookupSourceAndLineStarts(zone);
const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
- line_starts_reader.LocationForPosition(token_pos.value(), line, column);
- if (token_len != NULL) {
- *token_len = 1;
- // We don't explicitly save this data: Load the source
- // and find it from there.
- const String& source = String::Handle(zone, Source());
- if (!source.IsNull()) {
- intptr_t offset = token_pos.value();
- if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
- for (intptr_t i = offset + 1;
- i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
- ++*token_len;
- }
+ const intptr_t pos = token_pos.Pos();
+ line_starts_reader.LocationForPosition(pos, line, column);
+ if (token_len == nullptr) return;
+ *token_len = 1;
+ // We don't explicitly save this data: Load the source
+ // and find it from there.
+ const String& source = String::Handle(zone, Source());
+ if (!source.IsNull()) {
+ intptr_t offset = pos;
+ if (offset < source.Length() && IsIdentStartChar(source.CharAt(offset))) {
+ for (intptr_t i = offset + 1;
+ i < source.Length() && IsIdentChar(source.CharAt(i)); ++i) {
+ ++*token_len;
}
}
}
@@ -11321,16 +11315,10 @@
ASSERT(first_token_index != NULL && last_token_index != NULL);
ASSERT(line_number > 0);
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- LookupSourceAndLineStarts(zone);
- if (line_starts() == TypedData::null()) {
- // Scripts in the AOT snapshot do not have a line starts array.
- *first_token_index = TokenPosition::kNoSource;
- *last_token_index = TokenPosition::kNoSource;
- return;
- }
+ // Scripts in the AOT snapshot do not have a line starts array.
#if !defined(DART_PRECOMPILED_RUNTIME)
+ Zone* zone = Thread::Current()->zone();
+ LookupSourceAndLineStarts(zone);
const String& source = String::Handle(zone, Source());
intptr_t source_length;
if (source.IsNull()) {
@@ -11342,8 +11330,7 @@
source_length = source.Length();
}
const TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
- kernel::KernelLineStartsReader line_starts_reader(line_starts_data,
- Thread::Current()->zone());
+ kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
line_starts_reader.TokenRangeAtLine(source_length, line_number,
first_token_index, last_token_index);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -14359,8 +14346,8 @@
" %-13s level=%-3d"
" begin=%-3d end=%d\n",
i, LocalVarDescriptors::KindToCString(kind), index,
- static_cast<int>(info.begin_pos.value()),
- static_cast<int>(info.end_pos.value()));
+ static_cast<int>(info.begin_pos.Pos()),
+ static_cast<int>(info.end_pos.Pos()));
} else if (kind == LocalVarDescriptorsLayout::kContextVar) {
return Utils::SNPrint(
buffer, len,
@@ -16810,18 +16797,19 @@
}
TokenPosition ContextScope::TokenIndexAt(intptr_t scope_index) const {
- return TokenPosition(Smi::Value(VariableDescAddr(scope_index)->token_pos));
+ return TokenPosition::Deserialize(
+ Smi::Value(VariableDescAddr(scope_index)->token_pos));
}
void ContextScope::SetTokenIndexAt(intptr_t scope_index,
TokenPosition token_pos) const {
StoreSmi(&VariableDescAddr(scope_index)->token_pos,
- Smi::New(token_pos.value()));
+ Smi::New(token_pos.Serialize()));
}
TokenPosition ContextScope::DeclarationTokenIndexAt(
intptr_t scope_index) const {
- return TokenPosition(
+ return TokenPosition::Deserialize(
Smi::Value(VariableDescAddr(scope_index)->declaration_token_pos));
}
@@ -16829,7 +16817,7 @@
intptr_t scope_index,
TokenPosition declaration_token_pos) const {
StoreSmi(&VariableDescAddr(scope_index)->declaration_token_pos,
- Smi::New(declaration_token_pos.value()));
+ Smi::New(declaration_token_pos.Serialize()));
}
StringPtr ContextScope::NameAt(intptr_t scope_index) const {
@@ -24238,13 +24226,14 @@
intptr_t line = -1;
intptr_t column = -1;
- if (FLAG_precompiled_mode) {
- line = token_pos.value();
- } else if (token_pos.IsSourcePosition()) {
- ASSERT(!script.IsNull());
- script.GetTokenLocation(token_pos.SourcePosition(), &line, &column);
+ if (token_pos.IsReal()) {
+ if (FLAG_precompiled_mode) {
+ line = token_pos.Pos();
+ } else {
+ ASSERT(!script.IsNull());
+ script.GetTokenLocation(token_pos, &line, &column);
+ }
}
-
PrintSymbolicStackFrameIndex(buffer, frame_index);
PrintSymbolicStackFrameBody(buffer, function_name, url, line, column);
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index aab8456..b94c5a3 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2954,7 +2954,7 @@
TokenPosition token_pos() const {
#if defined(DART_PRECOMPILED_RUNTIME)
- return TokenPosition();
+ return TokenPosition::kNoSource;
#else
return raw_ptr()->token_pos_;
#endif
@@ -2963,7 +2963,7 @@
TokenPosition end_token_pos() const {
#if defined(DART_PRECOMPILED_RUNTIME)
- return TokenPosition();
+ return TokenPosition::kNoSource;
#else
return raw_ptr()->end_token_pos_;
#endif
@@ -2976,6 +2976,9 @@
#endif
}
+ // Returns the size of the source for this function.
+ intptr_t SourceSize() const;
+
intptr_t num_fixed_parameters() const {
return FunctionLayout::PackedNumFixedParameters::decode(
raw_ptr()->packed_fields_);
@@ -4540,9 +4543,6 @@
void SetLocationOffset(intptr_t line_offset, intptr_t col_offset) const;
- bool GetTokenLocationUsingLineStarts(TokenPosition token_pos,
- intptr_t* line,
- intptr_t* column) const;
void GetTokenLocation(TokenPosition token_pos,
intptr_t* line,
intptr_t* column,
@@ -5587,7 +5587,7 @@
if (!FLAG_precompiled_mode) {
cur_deopt_id_ += stream.ReadSLEB128();
- cur_token_pos_ += stream.ReadSLEB128();
+ cur_token_pos_ += stream.ReadSLEB128<int32_t>();
}
byte_index_ = stream.Position();
@@ -5600,7 +5600,9 @@
uword PcOffset() const { return cur_pc_offset_; }
intptr_t DeoptId() const { return cur_deopt_id_; }
- TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
+ TokenPosition TokenPos() const {
+ return TokenPosition::Deserialize(cur_token_pos_);
+ }
intptr_t TryIndex() const { return cur_try_index_; }
intptr_t YieldIndex() const { return cur_yield_index_; }
PcDescriptorsLayout::Kind Kind() const {
@@ -5630,7 +5632,7 @@
intptr_t cur_pc_offset_;
intptr_t cur_kind_;
intptr_t cur_deopt_id_;
- intptr_t cur_token_pos_;
+ int32_t cur_token_pos_;
intptr_t cur_try_index_;
intptr_t cur_yield_index_;
};
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1dfe634..459b279 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -808,7 +808,7 @@
JSONObject jsobj(&jsarray);
jsobj.AddProperty("name", String::Handle(target_name()).ToCString());
- jsobj.AddProperty("tokenPos", token_pos.value());
+ jsobj.AddProperty("tokenPos", static_cast<intptr_t>(token_pos.Serialize()));
// TODO(rmacnak): Figure out how to stringify DeoptReasons().
// jsobj.AddProperty("deoptReasons", ...);
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index cc5e5c1..fdd6784 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2914,18 +2914,18 @@
DescriptorList* builder = new DescriptorList(thread->zone());
// kind, pc_offset, deopt_id, token_pos, try_index, yield_index
- builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 1, TokenPosition(20),
- 1, 1);
- builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 20, 2, TokenPosition(30),
- 0, -1);
- builder->AddDescriptor(PcDescriptorsLayout::kOther, 30, 3, TokenPosition(40),
- 1, 10);
- builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 4, TokenPosition(40),
- 2, 20);
- builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 5, TokenPosition(80),
- 3, 30);
- builder->AddDescriptor(PcDescriptorsLayout::kOther, 80, 6, TokenPosition(150),
- 3, 30);
+ builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 1,
+ TokenPosition::Deserialize(20), 1, 1);
+ builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 20, 2,
+ TokenPosition::Deserialize(30), 0, -1);
+ builder->AddDescriptor(PcDescriptorsLayout::kOther, 30, 3,
+ TokenPosition::Deserialize(40), 1, 10);
+ builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 4,
+ TokenPosition::Deserialize(40), 2, 20);
+ builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 5,
+ TokenPosition::Deserialize(80), 3, 30);
+ builder->AddDescriptor(PcDescriptorsLayout::kOther, 80, 6,
+ TokenPosition::Deserialize(150), 3, 30);
PcDescriptors& descriptors = PcDescriptors::Handle();
descriptors ^= builder->FinalizePcDescriptors(0);
@@ -2945,7 +2945,7 @@
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(1, iter.YieldIndex());
- EXPECT_EQ(20, iter.TokenPos().value());
+ EXPECT_EQ(20, iter.TokenPos().Pos());
EXPECT_EQ(1, iter.TryIndex());
EXPECT_EQ(static_cast<uword>(10), iter.PcOffset());
EXPECT_EQ(1, iter.DeoptId());
@@ -2953,28 +2953,28 @@
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(-1, iter.YieldIndex());
- EXPECT_EQ(30, iter.TokenPos().value());
+ EXPECT_EQ(30, iter.TokenPos().Pos());
EXPECT_EQ(PcDescriptorsLayout::kDeopt, iter.Kind());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(10, iter.YieldIndex());
- EXPECT_EQ(40, iter.TokenPos().value());
+ EXPECT_EQ(40, iter.TokenPos().Pos());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(20, iter.YieldIndex());
- EXPECT_EQ(40, iter.TokenPos().value());
+ EXPECT_EQ(40, iter.TokenPos().Pos());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(30, iter.YieldIndex());
- EXPECT_EQ(80, iter.TokenPos().value());
+ EXPECT_EQ(80, iter.TokenPos().Pos());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(30, iter.YieldIndex());
- EXPECT_EQ(150, iter.TokenPos().value());
+ EXPECT_EQ(150, iter.TokenPos().Pos());
EXPECT_EQ(3, iter.TryIndex());
EXPECT_EQ(static_cast<uword>(80), iter.PcOffset());
- EXPECT_EQ(150, iter.TokenPos().value());
+ EXPECT_EQ(150, iter.TokenPos().Pos());
EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
EXPECT_EQ(false, iter.MoveNext());
@@ -2985,17 +2985,17 @@
// kind, pc_offset, deopt_id, token_pos, try_index
builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 1,
- TokenPosition(200), 1, 10);
+ TokenPosition::Deserialize(200), 1, 10);
builder->AddDescriptor(PcDescriptorsLayout::kDeopt, 200, 2,
- TokenPosition(300), 0, -1);
+ TokenPosition::Deserialize(300), 0, -1);
builder->AddDescriptor(PcDescriptorsLayout::kOther, 300, 3,
- TokenPosition(400), 1, 10);
- builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 4, TokenPosition(0),
- 2, 20);
+ TokenPosition::Deserialize(400), 1, 10);
+ builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 4,
+ TokenPosition::Deserialize(0), 2, 20);
builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 5,
- TokenPosition(800), 3, 30);
+ TokenPosition::Deserialize(800), 3, 30);
builder->AddDescriptor(PcDescriptorsLayout::kOther, 800, 6,
- TokenPosition(150), 3, 30);
+ TokenPosition::Deserialize(150), 3, 30);
PcDescriptors& descriptors = PcDescriptors::Handle();
descriptors ^= builder->FinalizePcDescriptors(0);
@@ -3015,7 +3015,7 @@
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(10, iter.YieldIndex());
- EXPECT_EQ(200, iter.TokenPos().value());
+ EXPECT_EQ(200, iter.TokenPos().Pos());
EXPECT_EQ(1, iter.TryIndex());
EXPECT_EQ(static_cast<uword>(100), iter.PcOffset());
EXPECT_EQ(1, iter.DeoptId());
@@ -3023,28 +3023,28 @@
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(-1, iter.YieldIndex());
- EXPECT_EQ(300, iter.TokenPos().value());
+ EXPECT_EQ(300, iter.TokenPos().Pos());
EXPECT_EQ(PcDescriptorsLayout::kDeopt, iter.Kind());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(10, iter.YieldIndex());
- EXPECT_EQ(400, iter.TokenPos().value());
+ EXPECT_EQ(400, iter.TokenPos().Pos());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(20, iter.YieldIndex());
- EXPECT_EQ(0, iter.TokenPos().value());
+ EXPECT_EQ(0, iter.TokenPos().Pos());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(30, iter.YieldIndex());
- EXPECT_EQ(800, iter.TokenPos().value());
+ EXPECT_EQ(800, iter.TokenPos().Pos());
EXPECT_EQ(true, iter.MoveNext());
EXPECT_EQ(30, iter.YieldIndex());
- EXPECT_EQ(150, iter.TokenPos().value());
+ EXPECT_EQ(150, iter.TokenPos().Pos());
EXPECT_EQ(3, iter.TryIndex());
EXPECT_EQ(static_cast<uword>(800), iter.PcOffset());
- EXPECT_EQ(150, iter.TokenPos().value());
+ EXPECT_EQ(150, iter.TokenPos().Pos());
EXPECT_EQ(PcDescriptorsLayout::kOther, iter.Kind());
EXPECT_EQ(false, iter.MoveNext());
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 4f88ae4..d539a35 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -174,7 +174,12 @@
intptr_t i = 0;
for (; i < source_position_ticks_.length(); i++) {
ProfileFunctionSourcePosition& position = source_position_ticks_[i];
- if (position.token_pos().value() == token_position.value()) {
+ const intptr_t cmp =
+ TokenPosition::CompareForSorting(position.token_pos(), token_position);
+ if (cmp > 0) {
+ // Found insertion point.
+ break;
+ } else if (cmp == 0) {
if (FLAG_trace_profiler_verbose) {
OS::PrintErr("Ticking source position %s %s\n",
exclusive ? "exclusive" : "inclusive",
@@ -184,9 +189,6 @@
position.Tick(exclusive);
return;
}
- if (position.token_pos().value() > token_position.value()) {
- break;
- }
}
// Add new one, sorted by token position value.
@@ -934,7 +936,7 @@
if (cache_entry->inlined_functions.length() == 0) {
*inlined_functions = NULL;
*inlined_token_positions = NULL;
- *token_position = cache_entry->token_position = TokenPosition();
+ *token_position = cache_entry->token_position = TokenPosition::kNoSource;
return;
}
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 0ad1e7f..a3d42a8 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -115,7 +115,7 @@
intptr_t offset;
GrowableArray<const Function*> inlined_functions;
GrowableArray<TokenPosition> inlined_token_positions;
- TokenPosition token_position;
+ TokenPosition token_position = TokenPosition::kNoSource;
};
static const intptr_t kCacheSize = 128;
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index 6c3589e..048a8bf 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -282,13 +282,10 @@
return NULL;
}
TokenPosition token_pos = pfsp.token_pos();
- if (!token_pos.IsSourcePosition()) {
+ if (!token_pos.IsReal()) {
// Not a location in a script.
return NULL;
}
- if (token_pos.IsSynthetic()) {
- token_pos = token_pos.FromSynthetic();
- }
intptr_t line = 0, column = 0, token_len = 0;
script.GetTokenLocation(token_pos, &line, &column, &token_len);
@@ -2315,10 +2312,10 @@
"}\n";
// Token position of * in `i * i`.
- const TokenPosition squarePosition = TokenPosition(19);
+ const TokenPosition squarePosition = TokenPosition::Deserialize(19);
// Token position of the call to `doWork`.
- const TokenPosition callPosition = TokenPosition(95);
+ const TokenPosition callPosition = TokenPosition::Deserialize(95);
DisableNativeProfileScope dnps;
// Disable profiling for this thread.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 19a1934..fd85941 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1919,9 +1919,12 @@
struct VarInfo {
int32_t index_kind = 0; // Bitfield for slot index on stack or in context,
// and Entry kind of type VarInfoKind.
- TokenPosition declaration_pos; // Token position of declaration.
- TokenPosition begin_pos; // Token position of scope start.
- TokenPosition end_pos; // Token position of scope end.
+ TokenPosition declaration_pos =
+ TokenPosition::kNoSource; // Token position of declaration.
+ TokenPosition begin_pos =
+ TokenPosition::kNoSource; // Token position of scope start.
+ TokenPosition end_pos =
+ TokenPosition::kNoSource; // Token position of scope end.
int16_t scope_id; // Scope to which the variable belongs.
VarInfoKind kind() const {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 853c1cac..639d149 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -87,7 +87,7 @@
reader->AddBackRef(object_id, &type, kIsDeserialized);
// Set all non object fields.
- type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
+ type.set_token_pos(TokenPosition::Deserialize(reader->Read<int32_t>()));
const uint8_t combined = reader->Read<uint8_t>();
type.set_type_state(combined >> 4);
type.set_nullability(static_cast<Nullability>(combined & 0xf));
@@ -160,7 +160,7 @@
writer->Write<bool>(typeclass_is_in_fullsnapshot);
// Write out all the non object pointer fields.
- writer->Write<int32_t>(token_pos_.SnapshotEncode());
+ writer->Write<int32_t>(token_pos_.Serialize());
const uint8_t combined = (type_state_ << 4) | nullability_;
ASSERT(type_state_ == (combined >> 4));
ASSERT(nullability_ == (combined & 0xf));
@@ -234,7 +234,7 @@
// Set all non object fields.
type_parameter.set_token_pos(
- TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
+ TokenPosition::Deserialize(reader->Read<int32_t>()));
type_parameter.set_index(reader->Read<int16_t>());
const uint8_t combined = reader->Read<uint8_t>();
type_parameter.set_flags(combined >> 4);
@@ -285,7 +285,7 @@
writer->WriteTags(writer->GetObjectTags(this));
// Write out all the non object pointer fields.
- writer->Write<int32_t>(token_pos_.SnapshotEncode());
+ writer->Write<int32_t>(token_pos_.Serialize());
writer->Write<int16_t>(index_);
const uint8_t combined = (flags_ << 4) | nullability_;
ASSERT(flags_ == (combined >> 4));
@@ -637,7 +637,7 @@
// Set all non object fields.
language_error.set_token_pos(
- TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
+ TokenPosition::Deserialize(reader->Read<int32_t>()));
language_error.set_report_after_token(reader->Read<bool>());
language_error.set_kind(reader->Read<uint8_t>());
@@ -662,7 +662,7 @@
writer->WriteTags(writer->GetObjectTags(this));
// Write out all the non object fields.
- writer->Write<int32_t>(token_pos_.SnapshotEncode());
+ writer->Write<int32_t>(token_pos_.Serialize());
writer->Write<bool>(report_after_token_);
writer->Write<uint8_t>(kind_);
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index c84dc26..155ac8e 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -32,8 +32,8 @@
function_level_(function_level),
loop_level_(loop_level),
context_level_(LocalScope::kUninitializedContextLevel),
- begin_token_pos_(TokenPosition::kNoSourcePos),
- end_token_pos_(TokenPosition::kNoSourcePos),
+ begin_token_pos_(TokenPosition::kNoSource),
+ end_token_pos_(TokenPosition::kNoSource),
variables_(),
labels_(),
context_variables_(),
@@ -779,8 +779,9 @@
desc.name = &Symbols::Empty(); // No name.
desc.info.set_kind(LocalVarDescriptorsLayout::kContextLevel);
desc.info.scope_id = 0;
- desc.info.begin_pos = TokenPosition(start_deopt_id);
- desc.info.end_pos = TokenPosition(end_deopt_id);
+ // We repurpose the token position fields to store deopt IDs in this case.
+ desc.info.begin_pos = TokenPosition::Deserialize(start_deopt_id);
+ desc.info.end_pos = TokenPosition::Deserialize(end_deopt_id);
desc.info.set_index(start_context_level);
Add(desc);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 6a674bb..6118c2b 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3283,8 +3283,8 @@
}
}
SourceReport report(report_set, compile_mode);
- report.PrintJSON(js, script, TokenPosition(start_pos),
- TokenPosition(end_pos));
+ report.PrintJSON(js, script, TokenPosition::Deserialize(start_pos),
+ TokenPosition::Deserialize(end_pos));
return true;
#endif // !DART_PRECOMPILED_RUNTIME
}
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index b52f017..d065499 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -26,8 +26,8 @@
compile_mode_(compile_mode),
thread_(NULL),
script_(NULL),
- start_pos_(TokenPosition::kNoSource),
- end_pos_(TokenPosition::kNoSource),
+ start_pos_(TokenPosition::kMinSource),
+ end_pos_(TokenPosition::kMaxSource),
profile_(Isolate::Current()),
next_script_index_(0) {}
@@ -51,8 +51,8 @@
TokenPosition end_pos) {
thread_ = thread;
script_ = script;
- start_pos_ = start_pos;
- end_pos_ = end_pos;
+ start_pos_ = TokenPosition::Max(start_pos, TokenPosition::kMinSource);
+ end_pos_ = TokenPosition::Min(end_pos, TokenPosition::kMaxSource);
ClearScriptTable();
if (IsReportRequested(kProfile)) {
// Build the profile.
@@ -79,10 +79,7 @@
// The function is from the wrong script.
return true;
}
- if (((start_pos_ > TokenPosition::kMinSource) &&
- (func.end_token_pos() < start_pos_)) ||
- ((end_pos_ > TokenPosition::kMinSource) &&
- (func.token_pos() > end_pos_))) {
+ if ((func.end_token_pos() < start_pos_) || (func.token_pos() > end_pos_)) {
// The function does not intersect with the requested token range.
return true;
}
@@ -129,10 +126,8 @@
// The field is from the wrong script.
return true;
}
- if (((start_pos_ > TokenPosition::kMinSource) &&
- (field.end_token_pos() < start_pos_)) ||
- ((end_pos_ > TokenPosition::kMinSource) &&
- (field.token_pos() > end_pos_))) {
+ if ((field.end_token_pos() < start_pos_) ||
+ (field.token_pos() > end_pos_)) {
// The field does not intersect with the requested token range.
return true;
}
@@ -195,9 +190,8 @@
const Function& function,
const Code& code) {
ASSERT(!code.IsNull());
- const TokenPosition begin_pos = function.token_pos();
- const TokenPosition end_pos = function.end_token_pos();
-
+ const TokenPosition& begin_pos = function.token_pos();
+ const TokenPosition& end_pos = function.end_token_pos();
ZoneGrowableArray<const ICData*>* ic_data_array =
new (zone()) ZoneGrowableArray<const ICData*>();
function.RestoreICDataMap(ic_data_array, false /* clone ic-data */);
@@ -214,8 +208,8 @@
ASSERT(iter.DeoptId() < ic_data_array->length());
const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
if (ic_data != NULL) {
- const TokenPosition token_pos = iter.TokenPos();
- if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ const TokenPosition& token_pos = iter.TokenPos();
+ if (!token_pos.IsWithin(begin_pos, end_pos)) {
// Does not correspond to a valid source position.
continue;
}
@@ -228,8 +222,8 @@
const Function& function,
const Code& code) {
ASSERT(!code.IsNull());
- const TokenPosition begin_pos = function.token_pos();
- const TokenPosition end_pos = function.end_token_pos();
+ const TokenPosition& begin_pos = function.token_pos();
+ const TokenPosition& end_pos = function.end_token_pos();
ZoneGrowableArray<const ICData*>* ic_data_array =
new (zone()) ZoneGrowableArray<const ICData*>();
@@ -241,7 +235,7 @@
const int kCoverageMiss = 1;
const int kCoverageHit = 2;
- intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
+ intptr_t func_length = function.SourceSize() + 1;
GrowableArray<char> coverage(func_length);
coverage.SetLength(func_length);
for (int i = 0; i < func_length; i++) {
@@ -262,8 +256,8 @@
ASSERT(iter.DeoptId() < ic_data_array->length());
const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
if (ic_data != NULL) {
- const TokenPosition token_pos = iter.TokenPos();
- if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ const TokenPosition& token_pos = iter.TokenPos();
+ if (!token_pos.IsWithin(begin_pos, end_pos)) {
// Does not correspond to a valid source position.
continue;
}
@@ -303,9 +297,9 @@
void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
const Function& func,
const Code& code) {
- const TokenPosition begin_pos = func.token_pos();
- const TokenPosition end_pos = func.end_token_pos();
- intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
+ const TokenPosition& begin_pos = func.token_pos();
+ const TokenPosition& end_pos = func.end_token_pos();
+ intptr_t func_length = func.SourceSize() + 1;
BitVector possible(zone(), func_length);
@@ -320,8 +314,8 @@
PcDescriptors::Iterator iter(descriptors, kSafepointKind);
while (iter.MoveNext()) {
- const TokenPosition token_pos = iter.TokenPos();
- if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ const TokenPosition& token_pos = iter.TokenPos();
+ if (!token_pos.IsWithin(begin_pos, end_pos)) {
// Does not correspond to a valid source position.
continue;
}
@@ -357,7 +351,7 @@
for (intptr_t i = 0; i < profile_function->NumSourcePositions(); i++) {
const ProfileFunctionSourcePosition& position =
profile_function->GetSourcePosition(i);
- if (position.token_pos().IsSourcePosition()) {
+ if (position.token_pos().IsReal()) {
// Add as an integer.
positions.AddValue(position.token_pos().Pos());
} else {
diff --git a/runtime/vm/source_report.h b/runtime/vm/source_report.h
index 4ec20c9..246f64a 100644
--- a/runtime/vm/source_report.h
+++ b/runtime/vm/source_report.h
@@ -47,8 +47,8 @@
// in the isolate.
void PrintJSON(JSONStream* js,
const Script& script,
- TokenPosition start_pos = TokenPosition::kNoSource,
- TokenPosition end_pos = TokenPosition::kNoSource);
+ TokenPosition start_pos = TokenPosition::kMinSource,
+ TokenPosition end_pos = TokenPosition::kMaxSource);
private:
void ClearScriptTable();
diff --git a/runtime/vm/token_position.cc b/runtime/vm/token_position.cc
index 0f8ae68..507a528 100644
--- a/runtime/vm/token_position.cc
+++ b/runtime/vm/token_position.cc
@@ -4,34 +4,29 @@
#include "vm/token_position.h"
+#include "vm/hash.h"
#include "vm/object.h"
+#include "vm/zone_text_buffer.h"
namespace dart {
-TokenPosition TokenPosition::SnapshotDecode(int32_t value) {
- return TokenPosition(static_cast<intptr_t>(value));
+intptr_t TokenPosition::Hash() const {
+ return FinalizeHash(value_, 31);
}
-int32_t TokenPosition::SnapshotEncode() {
+TokenPosition TokenPosition::Deserialize(int32_t value) {
+ return TokenPosition(value);
+}
+
+int32_t TokenPosition::Serialize() const {
return static_cast<int32_t>(value_);
}
-bool TokenPosition::IsSynthetic() const {
- if (value_ >= kMinSourcePos) {
- return false;
- }
- if (value_ < kLast.value()) {
- return true;
- }
- return false;
-}
-
#define DEFINE_VALUES(name, value) \
const TokenPosition TokenPosition::k##name(value);
SENTINEL_TOKEN_DESCRIPTORS(DEFINE_VALUES);
#undef DEFINE_VALUES
const TokenPosition TokenPosition::kMinSource(kMinSourcePos);
-
const TokenPosition TokenPosition::kMaxSource(kMaxSourcePos);
const char* TokenPosition::ToCString() const {
@@ -41,17 +36,16 @@
return #name;
SENTINEL_TOKEN_DESCRIPTORS(DEFINE_CASE);
#undef DEFINE_CASE
- default: {
- Zone* zone = Thread::Current()->zone();
- ASSERT(zone != NULL);
- if (IsSynthetic()) {
- // TODO(johnmccutchan): Print synthetic positions differently.
- return FromSynthetic().ToCString();
- } else {
- return OS::SCreate(zone, "%d", value_);
- }
- }
+ default:
+ break;
}
+ ASSERT(IsReal() || IsSynthetic());
+ ZoneTextBuffer buffer(Thread::Current()->zone());
+ if (IsSynthetic()) {
+ buffer.AddString("syn:");
+ }
+ buffer.Printf("%" Pd32 "", value_);
+ return buffer.buffer();
}
} // namespace dart
diff --git a/runtime/vm/token_position.h b/runtime/vm/token_position.h
index 270a14c..d15553e 100644
--- a/runtime/vm/token_position.h
+++ b/runtime/vm/token_position.h
@@ -17,14 +17,26 @@
// ClassifyingTokenPositions 1 -> -1 - 1
// ClassifyingTokenPositions N -> -1 - N
//
-// Synthetically created AstNodes are given real source positions but encoded
-// as negative numbers from [kSmiMin32, -1 - N]. For example:
+// Real token positions represent source offsets in some script, and are encoded
+// as non-negative values which are equal to that offset.
//
-// A source position of 0 in a synthetic AstNode would be encoded as -2 - N.
-// A source position of 1 in a synthetic AstNode would be encoded as -3 - N.
+// Synthetically created functions that correspond to user code are given
+// starting token positions unique from other synthetic functions. The value for
+// these token positions encode a unique non-negative value as a negative number
+// within [kSmiMin32, -1 - N).
//
-// All other AstNodes are given real source positions encoded as positive
-// integers.
+// For example:
+// A synthetic token with value 0 is encoded as ((-1 - N) - (0 + 1)) = -2 - N.
+// A synthetic token with value 1 is encoded as ((-1 - N) - (1 + 1)) = -3 - N.
+//
+// Note that the encoded value is _not_ related to any possible real token
+// position, as two real token positions for different scripts can have the same
+// value and thus cannot serve as a unique nonce for a synthetic node.
+//
+// All other nodes read from user code, such as non-synthetic functions, fields,
+// etc., are given real starting token positions. All nodes coming from user
+// code, both real or synthetic, with ending token positions have real ending
+// token positions.
//
// This organization allows for ~1 billion token positions.
@@ -44,56 +56,112 @@
V(DartCodeEpilogue, -13) \
V(Last, -14) // Always keep this at the end.
-// A token position representing a debug safe source (real) position,
-// non-debug safe source (synthetic) positions, or a classifying value used
+// A token position represents either a debug safe source (real) position,
+// non-debug safe unique (synthetic) position, or a classifying value used
// by the profiler.
class TokenPosition {
public:
- TokenPosition() : value_(kNoSource.value()) {}
+ intptr_t Hash() const;
- explicit TokenPosition(intptr_t value) : value_(value) {}
-
+ // Returns whether the token positions are equal. Defined for all token
+ // positions.
bool operator==(const TokenPosition& b) const { return value() == b.value(); }
+ // Returns whether the token positions are not equal. Defined for all token
+ // positions.
bool operator!=(const TokenPosition& b) const { return !(*this == b); }
- bool operator<(const TokenPosition& b) const {
- // TODO(johnmccutchan): Assert that this is a source position.
- return value() < b.value();
+ // Returns whether the token position is less than [b]. Only defined for
+ // real token positions.
+ inline bool operator<(const TokenPosition& b) const {
+ return Pos() < b.Pos();
}
- bool operator>(const TokenPosition& b) const {
- // TODO(johnmccutchan): Assert that this is a source position.
- return b < *this;
+ // Returns whether the token position is greater than [b]. Only defined for
+ // real token positions.
+ inline bool operator>(const TokenPosition& b) const { return b < *this; }
+
+ // Returns whether the token position is less than or equal to [b]. Only
+ // defined for real token positions.
+ inline bool operator<=(const TokenPosition& b) const { return !(*this > b); }
+
+ // Returns whether the token position is greater than or equal to [b]. Only
+ // defined for real token positions.
+ inline bool operator>=(const TokenPosition& b) const { return !(*this < b); }
+
+ // For real token positions, returns whether this is between [a] and [b],
+ // inclusive. If [a] or [b] is non-real, they are treated as less than
+ // any real token position.
+ //
+ // For synthetic token positions, returns whether [a] or [b] equals this.
+ //
+ // For other token positions, always returns false.
+ bool IsWithin(const TokenPosition& a, const TokenPosition& b) const {
+ if (IsReal()) return (a.value() <= value()) && (value() <= b.value());
+ if (IsSynthetic()) return (a == *this) || (b == *this);
+ return false;
}
- bool operator<=(const TokenPosition& b) {
- // TODO(johnmccutchan): Assert that this is a source position.
- return !(*this > b);
+ // Returns [a] if both positions are not real, the real position if only one
+ // of [a] and [b] is real, or the minimum position of [a] and [b].
+ static const TokenPosition& Min(const TokenPosition& a,
+ const TokenPosition& b) {
+ if (!b.IsReal()) return a;
+ if (!a.IsReal()) return b;
+ return b.value() < a.value() ? b : a;
+ }
+ // Returns [a] if both positions are not real, the real position if only one
+ // of [a] and [b] is real, or the maximum position of [a] and [b].
+ static const TokenPosition& Max(const TokenPosition& a,
+ const TokenPosition& b) {
+ if (!b.IsReal()) return a;
+ if (!a.IsReal()) return b;
+ return b.value() > a.value() ? b : a;
}
- bool operator>=(const TokenPosition& b) {
- // TODO(johnmccutchan): Assert that this is a source position.
- return !(*this < b);
+ // Compares two arbitrary source positions for use in sorting, where a
+ // negative return means [a] sorts before [b], a return of 0 means [a] is the
+ // same as [b], and a positive return means [a] sorts after [b].
+ //
+ // Does _not_ correspond to the relational operators on token positions, as
+ // this also allows comparison of kNoSource, classifying, and synthetic token
+ // positions to each other.
+ static intptr_t CompareForSorting(const TokenPosition& a,
+ const TokenPosition& b) {
+ return a.value() - b.value();
}
- static const intptr_t kMaxSentinelDescriptors = 64;
+ static constexpr int32_t kMaxSentinelDescriptors = 64;
#define DECLARE_VALUES(name, value) \
- static const intptr_t k##name##Pos = value; \
+ static constexpr int32_t k##name##Pos = value; \
static const TokenPosition k##name;
SENTINEL_TOKEN_DESCRIPTORS(DECLARE_VALUES);
#undef DECLARE_VALUES
- static const intptr_t kMinSourcePos = 0;
+ // Check assumptions used in Is<X> methods below.
+#define CHECK_VALUES(name, value) \
+ static_assert(k##name##Pos < 0, "Non-negative sentinel descriptor"); \
+ static_assert( \
+ k##name##Pos == kNoSourcePos || k##name##Pos <= kBoxPos, \
+ "Box sentinel descriptor is not greatest classifying sentinel value"); \
+ static_assert(kLastPos <= k##name##Pos, \
+ "Last sentinel descriptor is not least sentinel valu"); \
+ SENTINEL_TOKEN_DESCRIPTORS(CHECK_VALUES);
+#undef CHECK_VALUES
+ static_assert(kLastPos > -kMaxSentinelDescriptors,
+ "More sentinel descriptors than expected");
+
+ static constexpr int32_t kMinSourcePos = 0;
static const TokenPosition kMinSource;
- static const intptr_t kMaxSourcePos = kSmiMax32 - kMaxSentinelDescriptors - 2;
+ static constexpr int32_t kMaxSourcePos =
+ kSmiMax32 - kMaxSentinelDescriptors - 2;
static const TokenPosition kMaxSource;
- // Decode from a snapshot.
- static TokenPosition SnapshotDecode(int32_t value);
+ // Decode from a serialized form.
+ static TokenPosition Deserialize(int32_t value);
- // Encode for writing into a snapshot.
- int32_t SnapshotEncode();
+ // Encode into a serialized form.
+ int32_t Serialize() const;
// Given a real token position, returns the next real token position.
TokenPosition Next() {
@@ -101,88 +169,47 @@
return TokenPosition(value_ + 1);
}
- // The raw value.
- // TODO(johnmccutchan): Make this private.
- intptr_t value() const { return value_; }
-
- // Return the source position.
- intptr_t Pos() const {
- if (IsSynthetic()) {
- return FromSynthetic().Pos();
- }
+ // Return the source position for real token positions.
+ inline intptr_t Pos() const {
+ ASSERT(IsReal());
return value_;
}
// Is |this| a classifying sentinel source position?
// Classifying positions are used by the profiler to group instructions whose
// cost isn't naturally attributable to a source location.
- bool IsClassifying() const {
+ inline bool IsClassifying() const {
return (value_ >= kBox.value()) && (value_ <= kLast.value());
}
// Is |this| the no source position sentinel?
- bool IsNoSource() const { return *this == kNoSource; }
+ inline bool IsNoSource() const { return value_ == kNoSourcePos; }
// Is |this| a synthetic source position?
// Synthetic source positions are used by the profiler to attribute ticks to a
// pieces of source, but ignored by the debugger as potential breakpoints.
- bool IsSynthetic() const;
+ inline bool IsSynthetic() const { return value_ < kLastPos; }
// Is |this| a real source position?
- bool IsReal() const { return value_ >= kMinSourcePos; }
-
- // Is |this| a source position?
- bool IsSourcePosition() const { return IsReal() || IsSynthetic(); }
-
- // Convert |this| into a real source position. Sentinel values remain
- // unchanged.
- TokenPosition SourcePosition() const { return FromSynthetic(); }
+ inline bool IsReal() const { return value_ >= kMinSourcePos; }
// Is |this| a debug pause source position?
- bool IsDebugPause() const {
- // Sanity check some values here.
- ASSERT(kNoSource.value() == kNoSourcePos);
- ASSERT(kLast.value() < kNoSource.value());
- ASSERT(kLast.value() > -kMaxSentinelDescriptors);
- return IsReal();
- }
+ inline bool IsDebugPause() const { return IsReal(); }
- // Convert |this| into a synthetic source position. Sentinel values remain
- // unchanged.
- TokenPosition ToSynthetic() const {
- const intptr_t value = value_;
- if (IsClassifying() || IsNoSource()) {
- return *this;
- }
- if (IsSynthetic()) {
- return *this;
- }
- const TokenPosition synthetic_value =
- TokenPosition((kLast.value() - 1) - value);
- ASSERT(synthetic_value.IsSynthetic());
- ASSERT(synthetic_value.value() < kLast.value());
- return synthetic_value;
- }
-
- // Convert |this| from a synthetic source position. Sentinel values remain
- // unchanged.
- TokenPosition FromSynthetic() const {
- const intptr_t synthetic_value = value_;
- if (IsClassifying() || IsNoSource()) {
- return *this;
- }
- if (!IsSynthetic()) {
- return *this;
- }
- const TokenPosition value =
- TokenPosition(-synthetic_value + (kLast.value() - 1));
- ASSERT(!value.IsSynthetic());
- return value;
+ // Creates a synthetic source position from a non-negative value.
+ static TokenPosition Synthetic(intptr_t value) {
+ ASSERT(value >= 0 && value <= kMaxSourcePos);
+ return TokenPosition((kLastPos - 1) - value);
}
const char* ToCString() const;
private:
+ explicit TokenPosition(intptr_t value) : value_(value) {}
+
+ // The raw value of this TokenPosition.
+ intptr_t value() const { return value_; }
+
int32_t value_;
DISALLOW_ALLOCATION();
diff --git a/tools/VERSION b/tools/VERSION
index 46c6f42..c912081 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 157
+PRERELEASE 158
PRERELEASE_PATCH 0
\ No newline at end of file