Version 1.6.0-dev.9.3
svn merge -c 39268 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 39272 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
svn merge -c 39260 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@39285 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer/lib/src/generated/java_io.dart b/pkg/analyzer/lib/src/generated/java_io.dart
index 347463b..245bd04 100644
--- a/pkg/analyzer/lib/src/generated/java_io.dart
+++ b/pkg/analyzer/lib/src/generated/java_io.dart
@@ -112,7 +112,10 @@
bool isDirectory() {
return _newDirectory().existsSync();
}
- Uri toURI() => pathos.toUri(_path);
+ Uri toURI() {
+ String path = getAbsolutePath();
+ return pathos.toUri(path);
+ }
String readAsStringSync() => _newFile().readAsStringSync();
int lastModified() {
if (!_newFile().existsSync()) return 0;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 554ec4b..4e03306 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.22.0+1
+version: 0.22.0+2
author: Dart Team <misc@dartlang.org>
description: Static analyzer for Dart.
homepage: http://www.dartlang.org
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index f54e1e5..77f7694 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -8328,6 +8328,44 @@
EXPECT_EQ(0x4e8c, ext_utf16_str[i]);
}
+ // Test with a symbol (hash value should be preserved on externalization).
+ const char* symbol_ascii = "string";
+ expected_length = strlen(symbol_ascii);
+ Dart_Handle symbol_str =
+ Api::NewHandle(isolate, Symbols::New(symbol_ascii, expected_length));
+ EXPECT_VALID(symbol_str);
+ EXPECT(Dart_IsString(symbol_str));
+ EXPECT(Dart_IsStringLatin1(symbol_str));
+ EXPECT(!Dart_IsExternalString(symbol_str));
+ EXPECT_VALID(Dart_StringLength(symbol_str, &length));
+ EXPECT_EQ(expected_length, length);
+ EXPECT(Api::UnwrapStringHandle(isolate, symbol_str).HasHash());
+
+ uint8_t ext_symbol_ascii[kLength];
+ EXPECT_VALID(Dart_StringStorageSize(symbol_str, &size));
+ str = Dart_MakeExternalString(symbol_str,
+ ext_symbol_ascii,
+ size,
+ &peer8,
+ MakeExternalCback);
+ EXPECT(Api::UnwrapStringHandle(isolate, str).HasHash());
+ EXPECT(Api::UnwrapStringHandle(isolate, str).Hash() ==
+ Api::UnwrapStringHandle(isolate, symbol_str).Hash());
+ EXPECT(Dart_IsString(str));
+ EXPECT(Dart_IsString(symbol_str));
+ EXPECT(Dart_IsStringLatin1(str));
+ EXPECT(Dart_IsStringLatin1(symbol_str));
+ EXPECT(Dart_IsExternalString(str));
+ EXPECT(Dart_IsExternalString(symbol_str));
+ EXPECT_VALID(Dart_StringLength(str, &length));
+ EXPECT_EQ(expected_length, length);
+ EXPECT_VALID(Dart_StringLength(symbol_str, &length));
+ EXPECT_EQ(expected_length, length);
+ EXPECT(Dart_IdentityEquals(str, symbol_str));
+ for (intptr_t i = 0; i < length; i++) {
+ EXPECT_EQ(symbol_ascii[i], ext_symbol_ascii[i]);
+ }
+
Dart_ExitScope();
}
EXPECT_EQ(40, peer8);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 09058ab..eba4e8c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1890,18 +1890,62 @@
}
+class FunctionName {
+ public:
+ FunctionName(const String& name, String* tmp_string)
+ : name_(name), tmp_string_(tmp_string) {}
+ bool Matches(const Function& function) const {
+ if (name_.IsSymbol()) {
+ return name_.raw() == function.name();
+ } else {
+ *tmp_string_ = function.name();
+ return name_.Equals(*tmp_string_);
+ }
+ }
+ intptr_t Hash() const { return name_.Hash(); }
+ private:
+ const String& name_;
+ String* tmp_string_;
+};
+
+
+// Traits for looking up Functions by name.
+class ClassFunctionsTraits {
+ public:
+ // Called when growing the table.
+ static bool IsMatch(const Object& a, const Object& b) {
+ ASSERT(a.IsFunction() && b.IsFunction());
+ // Function objects are always canonical.
+ return a.raw() == b.raw();
+ }
+ static bool IsMatch(const FunctionName& name, const Object& obj) {
+ return name.Matches(Function::Cast(obj));
+ }
+ static uword Hash(const Object& key) {
+ return String::HashRawSymbol(Function::Cast(key).name());
+ }
+ static uword Hash(const FunctionName& name) {
+ return name.Hash();
+ }
+};
+typedef UnorderedHashSet<ClassFunctionsTraits> ClassFunctionsSet;
+
+
void Class::SetFunctions(const Array& value) const {
ASSERT(!value.IsNull());
-#if defined(DEBUG)
- // Verify that all the functions in the array have this class as owner.
- Function& func = Function::Handle();
- intptr_t len = value.Length();
- for (intptr_t i = 0; i < len; i++) {
- func ^= value.At(i);
- ASSERT(func.Owner() == raw());
- }
-#endif
StorePointer(&raw_ptr()->functions_, value.raw());
+ const intptr_t len = value.Length();
+ ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len));
+ if (len >= kFunctionLookupHashTreshold) {
+ Function& func = Function::Handle();
+ for (intptr_t i = 0; i < len; ++i) {
+ func ^= value.At(i);
+ // Verify that all the functions in the array have this class as owner.
+ ASSERT(func.Owner() == raw());
+ set.Insert(func);
+ }
+ }
+ StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
}
@@ -1909,7 +1953,17 @@
const Array& arr = Array::Handle(functions());
const Array& new_arr = Array::Handle(Array::Grow(arr, arr.Length() + 1));
new_arr.SetAt(arr.Length(), function);
- SetFunctions(new_arr);
+ StorePointer(&raw_ptr()->functions_, new_arr.raw());
+ // Add to hash table, if any.
+ const intptr_t new_len = new_arr.Length();
+ if (new_len == kFunctionLookupHashTreshold) {
+ // Transition to using hash table.
+ SetFunctions(new_arr);
+ } else if (new_len > kFunctionLookupHashTreshold) {
+ ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
+ set.Insert(function);
+ StorePointer(&raw_ptr()->functions_hash_table_, set.Release().raw());
+ }
}
@@ -3831,6 +3885,15 @@
ASSERT(!funcs.IsNull());
const intptr_t len = funcs.Length();
Function& function = isolate->FunctionHandle();
+ if (len >= kFunctionLookupHashTreshold) {
+ ClassFunctionsSet set(raw_ptr()->functions_hash_table_);
+ REUSABLE_STRING_HANDLESCOPE(isolate);
+ function ^= set.GetOrNull(FunctionName(name, &(isolate->StringHandle())));
+ // No mutations.
+ ASSERT(set.Release().raw() == raw_ptr()->functions_hash_table_);
+ return function.IsNull() ? Function::null()
+ : CheckFunctionType(function, kind);
+ }
if (name.IsSymbol()) {
// Quick Symbol compare.
NoGCScope no_gc;
@@ -17053,10 +17116,12 @@
tags = RawObject::ClassIdTag::update(class_id, tags);
raw_ptr()->tags_ = tags;
result = this->raw();
+ const uint8_t* ext_array = reinterpret_cast<const uint8_t*>(array);
ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
- reinterpret_cast<const uint8_t*>(array), peer, cback);
- result.SetLength(str_length);
- result.SetHash(0);
+ ext_array, peer, cback);
+ ASSERT(result.Length() == str_length);
+ ASSERT(!result.HasHash() ||
+ (result.Hash() == String::Hash(ext_array, str_length)));
ExternalOneByteString::SetExternalData(result, ext_data);
external_data = ext_data;
finalizer = ExternalOneByteString::Finalize;
@@ -17079,10 +17144,12 @@
tags = RawObject::ClassIdTag::update(class_id, tags);
raw_ptr()->tags_ = tags;
result = this->raw();
+ const uint16_t* ext_array = reinterpret_cast<const uint16_t*>(array);
ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
- reinterpret_cast<const uint16_t*>(array), peer, cback);
- result.SetLength(str_length);
- result.SetHash(0);
+ ext_array, peer, cback);
+ ASSERT(result.Length() == str_length);
+ ASSERT(!result.HasHash() ||
+ (result.Hash() == String::Hash(ext_array, str_length)));
ExternalTwoByteString::SetExternalData(result, ext_data);
external_data = ext_data;
finalizer = ExternalTwoByteString::Finalize;
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 892060d..cede5f6 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -949,6 +949,7 @@
// Returns true if non-static fields are defined.
bool HasInstanceFields() const;
+ // TODO(koda): Unite w/ hash table.
RawArray* functions() const { return raw_ptr()->functions_; }
void SetFunctions(const Array& value) const;
void AddFunction(const Function& function) const;
@@ -1211,6 +1212,9 @@
void CalculateFieldOffsets() const;
+ // functions_hash_table is in use iff there are at least this many functions.
+ static const intptr_t kFunctionLookupHashTreshold = 16;
+
// Initial value for the cached number of type arguments.
static const intptr_t kUnknownNumTypeArguments = -1;
@@ -5389,6 +5393,10 @@
this->SetHash(result);
return result;
}
+ bool HasHash() const {
+ ASSERT(Smi::New(0) == NULL);
+ return (raw_ptr()->hash_ != NULL);
+ }
static intptr_t hash_offset() { return OFFSET_OF(RawString, hash_); }
static intptr_t Hash(const String& str, intptr_t begin_index, intptr_t len);
@@ -5602,11 +5610,6 @@
bool Equals(const uint8_t* characters, intptr_t len) const;
static intptr_t Hash(const uint8_t* characters, intptr_t len);
- bool HasHash() const {
- ASSERT(Smi::New(0) == NULL);
- return (raw_ptr()->hash_ != NULL);
- }
-
void SetLength(intptr_t value) const {
// This is only safe because we create a new Smi, which does not cause
// heap allocation.
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index bff2eff..86db68a 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -499,6 +499,7 @@
RawString* name_;
RawString* user_name_;
RawArray* functions_;
+ RawArray* functions_hash_table_;
RawArray* fields_;
RawArray* offset_in_words_to_field_;
RawGrowableObjectArray* closure_functions_; // Local functions and literals.
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 401a5c2..0ccf8a0 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -333,6 +333,7 @@
isolate->object_store()->set_symbol_table(table.Release());
}
ASSERT(symbol.IsSymbol());
+ ASSERT(symbol.HasHash());
return symbol.raw();
}
diff --git a/tests/standalone/issue14236_test.dart b/tests/standalone/issue14236_test.dart
index f720a65..7e248f3 100644
--- a/tests/standalone/issue14236_test.dart
+++ b/tests/standalone/issue14236_test.dart
Binary files differ
diff --git a/tools/VERSION b/tools/VERSION
index 938a641..4ca5a22 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,4 +28,4 @@
MINOR 6
PATCH 0
PRERELEASE 9
-PRERELEASE_PATCH 2
+PRERELEASE_PATCH 3