Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(895)

Unified Diff: src/parser-symbol-table.cc

Issue 231073002: WIP: Parser: delay string internalization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: rebased Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser-symbol-table.h ('k') | src/preparser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser-symbol-table.cc
diff --git a/src/parser-symbol-table.cc b/src/parser-symbol-table.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e0e4a357ae1aabc1416475885cffd3570eb227c7
--- /dev/null
+++ b/src/parser-symbol-table.cc
@@ -0,0 +1,283 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "parser-symbol-table.h"
+
+#include "api.h"
+#include "objects.h"
+
+namespace v8 {
+namespace internal {
+
+namespace {
+
+template <typename Char>
+int vector_hash(Vector<const Char> string) {
+ int hash = 0;
+ for (int i = 0; i < string.length(); i++) {
+ int c = static_cast<int>(string[i]);
+ hash += c;
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ return hash;
+}
+
+
+bool vector_compare(void* a, void* b) {
+ ParserSymbolTable::Symbol* string1 =
+ reinterpret_cast<ParserSymbolTable::Symbol*>(a);
+ ParserSymbolTable::Symbol* string2 =
+ reinterpret_cast<ParserSymbolTable::Symbol*>(b);
+ if (string1->is_one_byte != string2->is_one_byte) return false;
+ if (string1->hash != string2->hash) return false;
ulan 2014/05/21 15:01:22 I think HashMap guarantees that the hashes are equ
marja 2014/05/21 17:16:45 Actually, not. Turns out this case is sometimes hi
+ int length = string1->literal_bytes.length();
+ if (string2->literal_bytes.length() != length) return false;
+ return memcmp(string1->literal_bytes.start(),
+ string2->literal_bytes.start(), length) == 0;
+}
+
+}
+
+
+ParserSymbolTable::ParserSymbolTable()
+ : literal_chars_(0),
+ symbol_keys_(0),
+ string_table_(vector_compare),
+ isolate_(NULL) {
+ {
ulan 2014/05/21 15:01:22 How about second order macro for this? :)
+ const char* data = "(anonymous function)";
+ anonymous_function_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 20));
+ }
+ {
+ const char* data = "arguments";
+ arguments_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 9));
+ }
+ {
+ const char* data = ".for";
+ dot_for_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 4));
+ }
+ {
+ const char* data = ".iterator";
+ dot_iterator_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 9));
+ }
+ {
+ const char* data = ".module";
+ dot_module_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 7));
+ }
+ {
+ const char* data = ".result";
+ dot_result_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 7));
+ }
+ {
+ const char* data = "";
+ empty_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 0));
+ }
+ {
+ const char* data = "eval";
+ eval_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 4));
+ }
+ {
+ const char* data = "InitializeConstGlobal";
+ initialize_const_global_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 21));
+ }
+ {
+ const char* data = "InitializeVarGlobal";
+ initialize_var_global_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 19));
+ }
+ {
+ const char* data = "MakeReferenceError";
+ make_reference_error_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 18));
+ }
+ {
+ const char* data = "MakeSyntaxError";
+ make_syntax_error_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 15));
+ }
+ {
+ const char* data = "MakeTypeError";
+ make_type_error_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 13));
+ }
+ {
+ const char* data = "module";
+ module_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 6));
+ }
+ {
+ const char* data = "native";
+ native_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 6));
+ }
+ {
+ const char* data = "prototype";
+ prototype_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 9));
+ }
+ {
+ const char* data = "this";
+ this_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 4));
+ }
+ {
+ const char* data = "use strict";
+ use_strict_string_ = GetOneByteSymbol(
+ Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), 10));
+ }
+}
+
+
+ParserSymbolTable::Symbol* ParserSymbolTable::GetOneByteSymbol(
+ Vector<const uint8_t> literal) {
+ return GetSymbol(vector_hash(literal), true, literal);
+}
+
+
+ParserSymbolTable::Symbol* ParserSymbolTable::GetTwoByteSymbol(
+ Vector<const uint16_t> literal) {
+ return GetSymbol(vector_hash(literal), false,
+ Vector<const byte>::cast(literal));
+}
+
+
+ParserSymbolTable::Symbol* ParserSymbolTable::GetSymbol(
+ Handle<String> literal) {
+ DisallowHeapAllocation no_gc;
+ String::FlatContent content = literal->GetFlatContent();
+ if (content.IsAscii()) {
+ return GetOneByteSymbol(content.ToOneByteVector());
+ }
+ ASSERT(content.IsTwoByte());
+ return GetTwoByteSymbol(content.ToUC16Vector());
+}
+
+
+bool ParserSymbolTable::SymbolMatches(Symbol* symbol, const char* data,
+ int length) {
+ if (symbol != NULL && symbol->is_one_byte &&
+ symbol->literal_bytes.length() == length) {
+ const char* token =
+ reinterpret_cast<const char*>(symbol->literal_bytes.start());
+ return !strncmp(token, data, length);
+ }
+ return false;
+}
+
+
+void ParserSymbolTable::Internalize(Isolate* isolate) {
+ for (HashMap::Entry* p = string_table_.Start(); p != NULL;
+ p = string_table_.Next(p)) {
+ ParserSymbolTable::Symbol* symbol =
+ reinterpret_cast<ParserSymbolTable::Symbol*>(p->key);
+ Internalize(symbol, isolate);
+ }
+ // FIXME: can we free the backing store now? Maybe not.
+ isolate_ = isolate;
+}
+
+
+bool ParserSymbolTable::IsArrayIndexSlow(Symbol* symbol, uint32_t* index) {
+ ASSERT(symbol != NULL);
+ if (!symbol->is_one_byte) return false;
+ if (symbol->literal_bytes.length() == 0 ||
+ symbol->literal_bytes.length() > String::kMaxArrayIndexSize)
+ return false;
+
+ uint16_t ch = symbol->literal_bytes.at(0);
+ // If the string begins with a '0' character, it must only consist
+ // of it to be a legal array index.
+ if (ch == '0') {
+ if (index != NULL) *index = 0;
+ return symbol->literal_bytes.length() == 1;
+ }
+
+ int d = ch - '0';
+ if (d < 0 || d > 9) return false;
+ uint32_t result = d;
+ for (int i = 1; i < symbol->literal_bytes.length(); ++i) {
+ d = symbol->literal_bytes.at(i) - '0';
+ if (d < 0 || d > 9) return false;
+ // Check that the new result is below the 32 bit limit.
+ if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
+ result = (result * 10) + d;
+ }
+ if (index != NULL) *index = result;
+ return true;
+}
+
+
+ParserSymbolTable::Symbol* ParserSymbolTable::GetSymbol(
+ int hash, bool is_one_byte, Vector<const byte> literal_bytes) {
+ // literal_bytes here points to whatever the user passed, and this is OK
+ // because we use vector_compare (which checks the contents) to compare
+ // against the Symbols which are in the string_table_. We should not return
+ // this Symbol.
+ Symbol key(is_one_byte, literal_bytes, hash);
+ HashMap::Entry* entry = string_table_.Lookup(&key, hash, true);
+ if (entry->value == NULL) {
+ // Copy literal contents for later comparison.
+ key.literal_bytes =
+ Vector<const byte>::cast(literal_chars_.AddBlock(literal_bytes));
+ // This Vector will be valid as long as the Collector is alive (meaning that
+ // the Symbol will not be moved).
+ Vector<Symbol> symbol = symbol_keys_.AddBlock(1, key);
+ entry->key = &symbol[0];
+ if (isolate_) {
+ Internalize(&symbol[0], isolate_);
+ }
+ entry->value = reinterpret_cast<void*>(1);
+ }
+ return reinterpret_cast<Symbol*>(entry->key);
+}
+
+
+void ParserSymbolTable::Internalize(ParserSymbolTable::Symbol* symbol, Isolate* isolate) {
+ ASSERT(symbol != NULL);
+ if (symbol->literal_bytes.length() == 0) {
+ symbol->string_ = isolate->factory()->empty_string();
+ }
+ else if (symbol->is_one_byte) {
+ symbol->string_ = isolate->factory()->InternalizeOneByteString(symbol->literal_bytes);
+ } else {
+ symbol->string_ = isolate->factory()->InternalizeTwoByteString(
+ Vector<const uint16_t>::cast(symbol->literal_bytes));
+ }
+}
+
+
+} } // namespace v8::internal
« no previous file with comments | « src/parser-symbol-table.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698