From 9ad39a8043657c18f9e0630c022ca5f2b5cfcfc1 Mon Sep 17 00:00:00 2001 From: "marja@chromium.org" Date: Wed, 18 Jun 2014 07:30:56 +0000 Subject: [PATCH] Revert "Parser: Delay internalizing strings and values." (r21841) Plus the fixes on top. Reason: regresses benchmarks (JSBench) and perf (morejs). TBR=rossberg@chromium.org BUG=385404 LOG=N Review URL: https://codereview.chromium.org/345513003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21882 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- BUILD.gn | 2 - include/v8.h | 2 +- src/ast-value-factory.cc | 368 --------------------------- src/ast-value-factory.h | 297 ---------------------- src/ast.cc | 34 +-- src/ast.h | 237 ++++++------------ src/compiler.cc | 17 +- src/compiler.h | 11 - src/func-name-inferrer.cc | 127 +++------- src/func-name-inferrer.h | 23 +- src/heap.h | 12 + src/hydrogen.cc | 3 - src/interface.cc | 24 +- src/interface.h | 12 +- src/objects.cc | 41 +++- src/parser.cc | 478 +++++++++++++++++------------------- src/parser.h | 112 ++++----- src/preparser.h | 36 ++- src/prettyprinter.cc | 14 +- src/prettyprinter.h | 5 +- src/rewriter.cc | 12 +- src/scanner.cc | 24 +- src/scanner.h | 7 +- src/scopeinfo.cc | 2 +- src/scopes.cc | 142 +++++------ src/scopes.h | 42 ++-- src/utils.cc | 20 -- src/utils.h | 30 --- src/variables.cc | 4 +- src/variables.h | 8 +- test/cctest/test-ast.cc | 2 +- test/cctest/test-parsing.cc | 22 +- tools/gyp/v8.gyp | 2 - tools/parser-shell.cc | 16 +- 34 files changed, 641 insertions(+), 1547 deletions(-) delete mode 100644 src/ast-value-factory.cc delete mode 100644 src/ast-value-factory.h diff --git a/BUILD.gn b/BUILD.gn index 74d2baa97..00ad3ccbd 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -365,8 +365,6 @@ source_set("v8_base") { "src/assembler.h", "src/assert-scope.h", "src/assert-scope.cc", - "src/ast-value-factory.cc", - "src/ast-value-factory.h", "src/ast.cc", "src/ast.h", "src/bignum-dtoa.cc", diff --git a/include/v8.h b/include/v8.h index 2739e070b..1db14733a 100644 --- a/include/v8.h +++ b/include/v8.h @@ -5543,7 +5543,7 @@ class Internals { static const int kNullValueRootIndex = 7; static const int kTrueValueRootIndex = 8; static const int kFalseValueRootIndex = 9; - static const int kEmptyStringRootIndex = 160; + static const int kEmptyStringRootIndex = 163; // The external allocation limit should be below 256 MB on all architectures // to avoid that resource-constrained embedders run low on memory. diff --git a/src/ast-value-factory.cc b/src/ast-value-factory.cc deleted file mode 100644 index bdc80d14d..000000000 --- a/src/ast-value-factory.cc +++ /dev/null @@ -1,368 +0,0 @@ -// 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 "src/ast-value-factory.h" - -#include "src/api.h" -#include "src/objects.h" - -namespace v8 { -namespace internal { - -namespace { - -template -int vector_hash(Vector string) { - int hash = 0; - for (int i = 0; i < string.length(); i++) { - int c = static_cast(string[i]); - hash += c; - hash += (hash << 10); - hash ^= (hash >> 6); - } - return hash; -} - - -// For using StringToArrayIndex. -class OneByteStringStream { - public: - explicit OneByteStringStream(Vector lb) : - literal_bytes_(lb), pos_(0) {} - - bool HasMore() { return pos_ < literal_bytes_.length(); } - uint16_t GetNext() { return literal_bytes_[pos_++]; } - - private: - Vector literal_bytes_; - int pos_; -}; - -} - - -bool AstString::AsArrayIndex(uint32_t* index) const { - if (!string_.is_null()) - return string_->AsArrayIndex(index); - if (!is_one_byte_ || literal_bytes_.length() == 0 || - literal_bytes_.length() > String::kMaxArrayIndexSize) - return false; - OneByteStringStream stream(literal_bytes_); - return StringToArrayIndex(&stream, index); -} - - -bool AstString::IsOneByteEqualTo(const char* data) const { - int length = static_cast(strlen(data)); - if (is_one_byte_ && literal_bytes_.length() == length) { - const char* token = reinterpret_cast(literal_bytes_.start()); - return !strncmp(token, data, length); - } - return false; -} - - -void AstString::Internalize(Isolate* isolate) { - if (!string_.is_null()) return; - if (literal_bytes_.length() == 0) { - string_ = isolate->factory()->empty_string(); - } else if (is_one_byte_) { - string_ = isolate->factory()->InternalizeOneByteString(literal_bytes_); - } else { - string_ = isolate->factory()->InternalizeTwoByteString( - Vector::cast(literal_bytes_)); - } -} - - -bool AstString::Compare(void* a, void* b) { - AstString* string1 = reinterpret_cast(a); - AstString* string2 = reinterpret_cast(b); - if (string1->is_one_byte_ != string2->is_one_byte_) return false; - if (string1->hash_ != string2->hash_) return false; - 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; -} - - -bool AstValue::IsPropertyName() const { - if (type_ == STRING) { - uint32_t index; - return !string_->AsArrayIndex(&index); - } - return false; -} - - -bool AstValue::BooleanValue() const { - switch (type_) { - case STRING: - ASSERT(string_ != NULL); - return !string_->IsEmpty(); - case SYMBOL: - UNREACHABLE(); - break; - case NUMBER: - return DoubleToBoolean(number_); - case SMI: - return smi_ != 0; - case STRING_ARRAY: - UNREACHABLE(); - break; - case BOOLEAN: - return bool_; - case NULL_TYPE: - return false; - case THE_HOLE: - UNREACHABLE(); - break; - case UNDEFINED: - return false; - } - UNREACHABLE(); - return false; -} - - -void AstValue::Internalize(Isolate* isolate) { - switch (type_) { - case STRING: - ASSERT(string_ != NULL); - // Strings are already internalized. - ASSERT(!string_->string().is_null()); - break; - case SYMBOL: - value_ = Object::GetProperty( - isolate, handle(isolate->native_context()->builtins()), - symbol_name_).ToHandleChecked(); - break; - case NUMBER: - value_ = isolate->factory()->NewNumber(number_, TENURED); - break; - case SMI: - value_ = handle(Smi::FromInt(smi_), isolate); - break; - case BOOLEAN: - if (bool_) { - value_ = isolate->factory()->true_value(); - } else { - value_ = isolate->factory()->false_value(); - } - break; - case STRING_ARRAY: { - ASSERT(strings_ != NULL); - Factory* factory = isolate->factory(); - int len = strings_->length(); - Handle elements = factory->NewFixedArray(len, TENURED); - for (int i = 0; i < len; i++) { - const AstString* string = (*strings_)[i]; - Handle element = string->string(); - // Strings are already internalized. - ASSERT(!element.is_null()); - elements->set(i, *element); - } - value_ = - factory->NewJSArrayWithElements(elements, FAST_ELEMENTS, TENURED); - break; - } - case NULL_TYPE: - value_ = isolate->factory()->null_value(); - break; - case THE_HOLE: - value_ = isolate->factory()->the_hole_value(); - break; - case UNDEFINED: - value_ = isolate->factory()->undefined_value(); - break; - } -} - - -const AstString* AstValueFactory::GetOneByteString( - Vector literal) { - return GetString(vector_hash(literal), true, literal); -} - - -const AstString* AstValueFactory::GetTwoByteString( - Vector literal) { - return GetString(vector_hash(literal), false, - Vector::cast(literal)); -} - - -const AstString* AstValueFactory::GetString(Handle literal) { - DisallowHeapAllocation no_gc; - String::FlatContent content = literal->GetFlatContent(); - if (content.IsAscii()) { - return GetOneByteString(content.ToOneByteVector()); - } - ASSERT(content.IsTwoByte()); - return GetTwoByteString(content.ToUC16Vector()); -} - - -void AstValueFactory::Internalize(Isolate* isolate) { - if (isolate_) { - // Everything is already internalized. - return; - } - // Strings need to be internalized before values, because values refer to - // strings. - for (HashMap::Entry* p = string_table_.Start(); p != NULL; - p = string_table_.Next(p)) { - AstString* string = reinterpret_cast(p->key); - string->Internalize(isolate); - } - for (int i = 0; i < values_.length(); ++i) { - values_[i]->Internalize(isolate); - } - isolate_ = isolate; -} - - -const AstValue* AstValueFactory::NewString(const AstString* string) { - AstValue* value = new (zone_) AstValue(string); - ASSERT(string != NULL); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewSymbol(const char* name) { - AstValue* value = new (zone_) AstValue(name); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewNumber(double number) { - AstValue* value = new (zone_) AstValue(number); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewSmi(int number) { - AstValue* value = - new (zone_) AstValue(AstValue::SMI, number); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewBoolean(bool b) { - AstValue* value = new (zone_) AstValue(b); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewStringList( - ZoneList* strings) { - AstValue* value = new (zone_) AstValue(strings); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewNull() { - AstValue* value = new (zone_) AstValue(AstValue::NULL_TYPE); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewUndefined() { - AstValue* value = new (zone_) AstValue(AstValue::UNDEFINED); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstValue* AstValueFactory::NewTheHole() { - AstValue* value = new (zone_) AstValue(AstValue::THE_HOLE); - if (isolate_) { - value->Internalize(isolate_); - } - values_.Add(value); - return value; -} - - -const AstString* AstValueFactory::GetString(int hash, bool is_one_byte, - Vector 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 AstStrings which are in the string_table_. We should not return - // this AstString. - AstString 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::cast(literal_chars_.AddBlock(literal_bytes)); - // This Vector will be valid as long as the Collector is alive (meaning that - // the AstString will not be moved). - Vector new_string = string_table_keys_.AddBlock(1, key); - entry->key = &new_string[0]; - if (isolate_) { - new_string[0].Internalize(isolate_); - } - entry->value = reinterpret_cast(1); - } - return reinterpret_cast(entry->key); -} - - -} } // namespace v8::internal diff --git a/src/ast-value-factory.h b/src/ast-value-factory.h deleted file mode 100644 index 7749b5cf3..000000000 --- a/src/ast-value-factory.h +++ /dev/null @@ -1,297 +0,0 @@ -// 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. - -#ifndef V8_AST_VALUE_FACTORY_H_ -#define V8_AST_VALUE_FACTORY_H_ - -#include "src/api.h" -#include "src/hashmap.h" -#include "src/utils.h" - -// AstString, AstValue and AstValueFactory are for storing strings and values -// independent of the V8 heap and internalizing them later. During parsing, -// AstStrings and AstValues are created and stored outside the heap, in -// AstValueFactory. After parsing, the strings and values are internalized -// (moved into the V8 heap). -namespace v8 { -namespace internal { - -class AstString { - public: - AstString(bool i, Vector lb, int h) - : is_one_byte_(i), - literal_bytes_(lb), - hash_(h) {} - - AstString() - : is_one_byte_(true), - hash_(0) {} - - bool AsArrayIndex(uint32_t* index) const; - - // The string is not null-terminated, use length() to find out the length. - const unsigned char* raw_data() const { return literal_bytes_.start(); } - int length() const { - if (is_one_byte_) - return literal_bytes_.length(); - return literal_bytes_.length() / 2; - } - bool is_one_byte() const { return is_one_byte_; } - bool IsEmpty() const { return literal_bytes_.length() == 0; } - bool IsOneByteEqualTo(const char* data) const; - uint16_t FirstCharacter() const { - if (is_one_byte_) - return literal_bytes_[0]; - const uint16_t* c = - reinterpret_cast(literal_bytes_.start()); - return *c; - } - - // Puts the string into the V8 heap. - void Internalize(Isolate* isolate); - - // This function can be called after internalizing. - V8_INLINE Handle string() const { - ASSERT(!string_.is_null()); - return string_; - } - - // For storing AstStrings in a hash map. - int hash() const { return hash_; } - static bool Compare(void* a, void* b); - - private: - friend class AstValueFactory; - - bool is_one_byte_; - // Weak. Points to memory owned by AstValueFactory. - Vector literal_bytes_; - int hash_; - - // This is null until the string is internalized. - Handle string_; -}; - - -// AstValue is either a string, a number, a string array, a boolean, or a -// special value (null, undefined, the hole). -class AstValue : public ZoneObject { - public: - bool IsString() const { - return type_ == STRING; - } - - bool IsNumber() const { - return type_ == NUMBER || type_ == SMI; - } - - const AstString* AsString() const { - if (type_ == STRING) - return string_; - UNREACHABLE(); - return 0; - } - - double AsNumber() const { - if (type_ == NUMBER) - return number_; - if (type_ == SMI) - return smi_; - UNREACHABLE(); - return 0; - } - - bool EqualsString(const AstString* string) const { - return type_ == STRING && string_ == string; - } - - bool IsPropertyName() const; - - bool BooleanValue() const; - - void Internalize(Isolate* isolate); - - // Can be called after Internalize has been called. - V8_INLINE Handle value() const { - if (type_ == STRING) { - return string_->string(); - } - ASSERT(!value_.is_null()); - return value_; - } - - private: - friend class AstValueFactory; - - enum Type { - STRING, - SYMBOL, - NUMBER, - SMI, - BOOLEAN, - STRING_ARRAY, - NULL_TYPE, - UNDEFINED, - THE_HOLE - }; - - explicit AstValue(const AstString* s) : type_(STRING) { string_ = s; } - - explicit AstValue(const char* name) : type_(SYMBOL) { symbol_name_ = name; } - - explicit AstValue(double n) : type_(NUMBER) { number_ = n; } - - AstValue(Type t, int i) : type_(t) { - ASSERT(type_ == SMI); - smi_ = i; - } - - explicit AstValue(bool b) : type_(BOOLEAN) { bool_ = b; } - - explicit AstValue(ZoneList* s) : type_(STRING_ARRAY) { - strings_ = s; - } - - explicit AstValue(Type t) : type_(t) { - ASSERT(t == NULL_TYPE || t == UNDEFINED || t == THE_HOLE); - } - - Type type_; - - // Uninternalized value. - union { - const AstString* string_; - double number_; - int smi_; - bool bool_; - ZoneList* strings_; - const char* symbol_name_; - }; - - // Internalized value (empty before internalized). - Handle value_; -}; - - -// For generating string constants. -#define STRING_CONSTANTS(F) \ - F(anonymous_function, "(anonymous function)") \ - F(arguments, "arguments") \ - F(done, "done") \ - F(dot_for, ".for") \ - F(dot_generator, ".generator") \ - F(dot_generator_object, ".generator_object") \ - F(dot_iterable, ".iterable") \ - F(dot_iterator, ".iterator") \ - F(dot_module, ".module") \ - F(dot_result, ".result") \ - F(empty, "") \ - F(eval, "eval") \ - F(initialize_const_global, "initializeConstGlobal") \ - F(initialize_var_global, "initializeVarGlobal") \ - F(make_reference_error, "MakeReferenceError") \ - F(make_syntax_error, "MakeSyntaxError") \ - F(make_type_error, "MakeTypeError") \ - F(module, "module") \ - F(native, "native") \ - F(next, "next") \ - F(proto, "__proto__") \ - F(prototype, "prototype") \ - F(this, "this") \ - F(use_strict, "use strict") \ - F(value, "value") - -class AstValueFactory { - public: - explicit AstValueFactory(Zone* zone) - : literal_chars_(0), - string_table_keys_(0), - string_table_(AstString::Compare), - zone_(zone), - isolate_(NULL) { -#define F(name, str) { \ - const char* data = str; \ - name##_string_ = GetOneByteString( \ - Vector(reinterpret_cast(data), \ - static_cast(strlen(data)))); \ - } - STRING_CONSTANTS(F) -#undef F - } - - const AstString* GetOneByteString(Vector literal); - const AstString* GetTwoByteString(Vector literal); - const AstString* GetString(Handle literal); - - void Internalize(Isolate* isolate); - bool IsInternalized() { - return isolate_ != NULL; - } - -#define F(name, str) \ - const AstString* name##_string() const { return name##_string_; } - STRING_CONSTANTS(F) -#undef F - - const AstValue* NewString(const AstString* string); - // A JavaScript symbol (ECMA-262 edition 6). - const AstValue* NewSymbol(const char* name); - const AstValue* NewNumber(double number); - const AstValue* NewSmi(int number); - const AstValue* NewBoolean(bool b); - const AstValue* NewStringList(ZoneList* strings); - const AstValue* NewNull(); - const AstValue* NewUndefined(); - const AstValue* NewTheHole(); - - private: - const AstString* GetString(int hash, bool is_one_byte, - Vector literal_bytes); - - // All strings are copied here, one after another (no NULLs inbetween). - Collector literal_chars_; - // List of all AstStrings we have created; keys of string_table_ are pointers - // into AstStrings in string_table_keys_. - Collector string_table_keys_; - HashMap string_table_; - // For keeping track of all AstValues we've created (so that they can be - // internalized later). - List values_; - Zone* zone_; - Isolate* isolate_; - -#define F(name, str) \ - const AstString* name##_string_; - STRING_CONSTANTS(F) -#undef F -}; - -} } // namespace v8::internal - -#undef STRING_CONSTANTS - -#endif // V8_AST_VALUE_FACTORY_H_ diff --git a/src/ast.cc b/src/ast.cc index dbbba830a..d332f4a3c 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -55,13 +55,14 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const { // The global identifier "undefined" is immutable. Everything // else could be reassigned. return var != NULL && var->location() == Variable::UNALLOCATED && - var_proxy->raw_name()->IsOneByteEqualTo("undefined"); + String::Equals(var_proxy->name(), + isolate->factory()->undefined_string()); } VariableProxy::VariableProxy(Zone* zone, Variable* var, int position) : Expression(zone, position), - name_(var->raw_name()), + name_(var->name()), var_(NULL), // Will be set by the call to BindTo. is_this_(var->is_this()), is_trivial_(false), @@ -72,7 +73,7 @@ VariableProxy::VariableProxy(Zone* zone, Variable* var, int position) VariableProxy::VariableProxy(Zone* zone, - const AstString* name, + Handle name, bool is_this, Interface* interface, int position) @@ -83,6 +84,8 @@ VariableProxy::VariableProxy(Zone* zone, is_trivial_(false), is_lvalue_(false), interface_(interface) { + // Names must be canonicalized for fast equality checks. + ASSERT(name->IsInternalizedString()); } @@ -90,7 +93,7 @@ void VariableProxy::BindTo(Variable* var) { ASSERT(var_ == NULL); // must be bound only once ASSERT(var != NULL); // must bind ASSERT(!FLAG_harmony_modules || interface_->IsUnified(var->interface())); - ASSERT((is_this() && var->is_this()) || name_ == var->raw_name()); + ASSERT((is_this() && var->is_this()) || name_.is_identical_to(var->name())); // Ideally CONST-ness should match. However, this is very hard to achieve // because we don't know the exact semantics of conflicting (const and // non-const) multiple variable declarations, const vars introduced via @@ -177,13 +180,15 @@ void FunctionLiteral::InitializeSharedInfo( } -ObjectLiteralProperty::ObjectLiteralProperty(Zone* zone, - AstValueFactory* ast_value_factory, - Literal* key, Expression* value) { +ObjectLiteralProperty::ObjectLiteralProperty( + Zone* zone, Literal* key, Expression* value) { emit_store_ = true; key_ = key; value_ = value; - if (key->raw_value()->EqualsString(ast_value_factory->proto_string())) { + Handle k = key->value(); + if (k->IsInternalizedString() && + String::Equals(Handle::cast(k), + zone->isolate()->factory()->proto_string())) { kind_ = PROTOTYPE; } else if (value_->AsMaterializedLiteral() != NULL) { kind_ = MATERIALIZED_LITERAL; @@ -1117,8 +1122,9 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { // optimize them. add_flag(kDontInline); } else if (node->function()->intrinsic_type == Runtime::INLINE && - (node->raw_name()->IsOneByteEqualTo("_ArgumentsLength") || - node->raw_name()->IsOneByteEqualTo("_Arguments"))) { + (node->name()->IsOneByteEqualTo( + STATIC_ASCII_VECTOR("_ArgumentsLength")) || + node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) { // Don't inline the %_ArgumentsLength or %_Arguments because their // implementation will not work. There is no stack frame to get them // from. @@ -1133,17 +1139,17 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { Handle Literal::ToString() { - if (value_->IsString()) return value_->AsString()->string(); + if (value_->IsString()) return Handle::cast(value_); ASSERT(value_->IsNumber()); char arr[100]; Vector buffer(arr, ARRAY_SIZE(arr)); const char* str; - if (value()->IsSmi()) { + if (value_->IsSmi()) { // Optimization only, the heap number case would subsume this. - SNPrintF(buffer, "%d", Smi::cast(*value())->value()); + SNPrintF(buffer, "%d", Smi::cast(*value_)->value()); str = arr; } else { - str = DoubleToCString(value()->Number(), buffer); + str = DoubleToCString(value_->Number(), buffer); } return isolate_->factory()->NewStringFromAsciiChecked(str); } diff --git a/src/ast.h b/src/ast.h index b84a4c8e1..3036fccbd 100644 --- a/src/ast.h +++ b/src/ast.h @@ -8,7 +8,6 @@ #include "src/v8.h" #include "src/assembler.h" -#include "src/ast-value-factory.h" #include "src/factory.h" #include "src/feedback-slots.h" #include "src/isolate.h" @@ -368,14 +367,11 @@ class Expression : public AstNode { protected: Expression(Zone* zone, int pos) : AstNode(pos), - zone_(zone), bounds_(Bounds::Unbounded(zone)), id_(GetNextId(zone)), test_id_(GetNextId(zone)) {} void set_to_boolean_types(byte types) { to_boolean_types_ = types; } - Zone* zone_; - private: Bounds bounds_; byte to_boolean_types_; @@ -394,7 +390,7 @@ class BreakableStatement : public Statement { // The labels associated with this statement. May be NULL; // if it is != NULL, guaranteed to contain at least one entry. - ZoneList* labels() const { return labels_; } + ZoneStringList* labels() const { return labels_; } // Type testing & conversion. virtual BreakableStatement* AsBreakableStatement() V8_FINAL V8_OVERRIDE { @@ -414,7 +410,7 @@ class BreakableStatement : public Statement { protected: BreakableStatement( - Zone* zone, ZoneList* labels, + Zone* zone, ZoneStringList* labels, BreakableType breakable_type, int position) : Statement(zone, position), labels_(labels), @@ -426,7 +422,7 @@ class BreakableStatement : public Statement { private: - ZoneList* labels_; + ZoneStringList* labels_; BreakableType breakable_type_; Label break_target_; const BailoutId entry_id_; @@ -457,7 +453,7 @@ class Block V8_FINAL : public BreakableStatement { protected: Block(Zone* zone, - ZoneList* labels, + ZoneStringList* labels, int capacity, bool is_initializer_block, int pos) @@ -666,15 +662,18 @@ class ModulePath V8_FINAL : public Module { DECLARE_NODE_TYPE(ModulePath) Module* module() const { return module_; } - Handle name() const { return name_->string(); } + Handle name() const { return name_; } protected: - ModulePath(Zone* zone, Module* module, const AstString* name, int pos) - : Module(zone, pos), module_(module), name_(name) {} + ModulePath(Zone* zone, Module* module, Handle name, int pos) + : Module(zone, pos), + module_(module), + name_(name) { + } private: Module* module_; - const AstString* name_; + Handle name_; }; @@ -731,7 +730,7 @@ class IterationStatement : public BreakableStatement { Label* continue_target() { return &continue_target_; } protected: - IterationStatement(Zone* zone, ZoneList* labels, int pos) + IterationStatement(Zone* zone, ZoneStringList* labels, int pos) : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), body_(NULL), osr_entry_id_(GetNextId(zone)) { @@ -765,7 +764,7 @@ class DoWhileStatement V8_FINAL : public IterationStatement { BailoutId BackEdgeId() const { return back_edge_id_; } protected: - DoWhileStatement(Zone* zone, ZoneList* labels, int pos) + DoWhileStatement(Zone* zone, ZoneStringList* labels, int pos) : IterationStatement(zone, labels, pos), cond_(NULL), continue_id_(GetNextId(zone)), @@ -802,7 +801,7 @@ class WhileStatement V8_FINAL : public IterationStatement { BailoutId BodyId() const { return body_id_; } protected: - WhileStatement(Zone* zone, ZoneList* labels, int pos) + WhileStatement(Zone* zone, ZoneStringList* labels, int pos) : IterationStatement(zone, labels, pos), cond_(NULL), may_have_function_literal_(true), @@ -853,7 +852,7 @@ class ForStatement V8_FINAL : public IterationStatement { void set_loop_variable(Variable* var) { loop_variable_ = var; } protected: - ForStatement(Zone* zone, ZoneList* labels, int pos) + ForStatement(Zone* zone, ZoneStringList* labels, int pos) : IterationStatement(zone, labels, pos), init_(NULL), cond_(NULL), @@ -895,8 +894,11 @@ class ForEachStatement : public IterationStatement { Expression* subject() const { return subject_; } protected: - ForEachStatement(Zone* zone, ZoneList* labels, int pos) - : IterationStatement(zone, labels, pos), each_(NULL), subject_(NULL) {} + ForEachStatement(Zone* zone, ZoneStringList* labels, int pos) + : IterationStatement(zone, labels, pos), + each_(NULL), + subject_(NULL) { + } private: Expression* each_; @@ -932,7 +934,7 @@ class ForInStatement V8_FINAL : public ForEachStatement, virtual BailoutId StackCheckId() const V8_OVERRIDE { return body_id_; } protected: - ForInStatement(Zone* zone, ZoneList* labels, int pos) + ForInStatement(Zone* zone, ZoneStringList* labels, int pos) : ForEachStatement(zone, labels, pos), for_in_type_(SLOW_FOR_IN), for_in_feedback_slot_(kInvalidFeedbackSlot), @@ -1002,7 +1004,7 @@ class ForOfStatement V8_FINAL : public ForEachStatement { BailoutId BackEdgeId() const { return back_edge_id_; } protected: - ForOfStatement(Zone* zone, ZoneList* labels, int pos) + ForOfStatement(Zone* zone, ZoneStringList* labels, int pos) : ForEachStatement(zone, labels, pos), assign_iterator_(NULL), next_result_(NULL), @@ -1163,7 +1165,7 @@ class SwitchStatement V8_FINAL : public BreakableStatement { ZoneList* cases() const { return cases_; } protected: - SwitchStatement(Zone* zone, ZoneList* labels, int pos) + SwitchStatement(Zone* zone, ZoneStringList* labels, int pos) : BreakableStatement(zone, labels, TARGET_FOR_ANONYMOUS, pos), tag_(NULL), cases_(NULL) { } @@ -1343,28 +1345,26 @@ class Literal V8_FINAL : public Expression { DECLARE_NODE_TYPE(Literal) virtual bool IsPropertyName() const V8_OVERRIDE { - return value_->IsPropertyName(); + if (value_->IsInternalizedString()) { + uint32_t ignored; + return !String::cast(*value_)->AsArrayIndex(&ignored); + } + return false; } Handle AsPropertyName() { ASSERT(IsPropertyName()); - return Handle::cast(value()); - } - - const AstString* AsRawPropertyName() { - ASSERT(IsPropertyName()); - return value_->AsString(); + return Handle::cast(value_); } virtual bool ToBooleanIsTrue() const V8_OVERRIDE { - return value()->BooleanValue(); + return value_->BooleanValue(); } virtual bool ToBooleanIsFalse() const V8_OVERRIDE { - return !value()->BooleanValue(); + return !value_->BooleanValue(); } - Handle value() const { return value_->value(); } - const AstValue* raw_value() const { return value_; } + Handle value() const { return value_; } // Support for using Literal as a HashMap key. NOTE: Currently, this works // only for string and number literals! @@ -1379,7 +1379,7 @@ class Literal V8_FINAL : public Expression { TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); } protected: - Literal(Zone* zone, const AstValue* value, int position) + Literal(Zone* zone, Handle value, int position) : Expression(zone, position), value_(value), isolate_(zone->isolate()) { } @@ -1387,7 +1387,7 @@ class Literal V8_FINAL : public Expression { private: Handle ToString(); - const AstValue* value_; + Handle value_; // TODO(dcarney): remove. this is only needed for Match and Hash. Isolate* isolate_; }; @@ -1458,8 +1458,7 @@ class ObjectLiteralProperty V8_FINAL : public ZoneObject { PROTOTYPE // Property is __proto__. }; - ObjectLiteralProperty(Zone* zone, AstValueFactory* ast_value_factory, - Literal* key, Expression* value); + ObjectLiteralProperty(Zone* zone, Literal* key, Expression* value); Literal* key() { return key_; } Expression* value() { return value_; } @@ -1558,13 +1557,13 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral { public: DECLARE_NODE_TYPE(RegExpLiteral) - Handle pattern() const { return pattern_->string(); } - Handle flags() const { return flags_->string(); } + Handle pattern() const { return pattern_; } + Handle flags() const { return flags_; } protected: RegExpLiteral(Zone* zone, - const AstString* pattern, - const AstString* flags, + Handle pattern, + Handle flags, int literal_index, int pos) : MaterializedLiteral(zone, literal_index, pos), @@ -1574,8 +1573,8 @@ class RegExpLiteral V8_FINAL : public MaterializedLiteral { } private: - const AstString* pattern_; - const AstString* flags_; + Handle pattern_; + Handle flags_; }; @@ -1626,12 +1625,15 @@ class VariableProxy V8_FINAL : public Expression { return var_ == NULL ? true : var_->IsValidReference(); } + bool IsVariable(Handle n) const { + return !is_this() && name().is_identical_to(n); + } + bool IsArguments() const { return var_ != NULL && var_->is_arguments(); } bool IsLValue() const { return is_lvalue_; } - Handle name() const { return name_->string(); } - const AstString* raw_name() const { return name_; } + Handle name() const { return name_; } Variable* var() const { return var_; } bool is_this() const { return is_this_; } Interface* interface() const { return interface_; } @@ -1647,12 +1649,12 @@ class VariableProxy V8_FINAL : public Expression { VariableProxy(Zone* zone, Variable* var, int position); VariableProxy(Zone* zone, - const AstString* name, + Handle name, bool is_this, Interface* interface, int position); - const AstString* name_; + Handle name_; Variable* var_; // resolved variable, or NULL bool is_this_; bool is_trivial_; @@ -1898,8 +1900,7 @@ class CallRuntime V8_FINAL : public Expression { public: DECLARE_NODE_TYPE(CallRuntime) - Handle name() const { return raw_name_->string(); } - const AstString* raw_name() const { return raw_name_; } + Handle name() const { return name_; } const Runtime::Function* function() const { return function_; } ZoneList* arguments() const { return arguments_; } bool is_jsruntime() const { return function_ == NULL; } @@ -1908,17 +1909,17 @@ class CallRuntime V8_FINAL : public Expression { protected: CallRuntime(Zone* zone, - const AstString* name, + Handle name, const Runtime::Function* function, ZoneList* arguments, int pos) : Expression(zone, pos), - raw_name_(name), + name_(name), function_(function), arguments_(arguments) { } private: - const AstString* raw_name_; + Handle name_; const Runtime::Function* function_; ZoneList* arguments_; }; @@ -2312,8 +2313,7 @@ class FunctionLiteral V8_FINAL : public Expression { DECLARE_NODE_TYPE(FunctionLiteral) - Handle name() const { return raw_name_->string(); } - const AstString* raw_name() const { return raw_name_; } + Handle name() const { return name_; } Scope* scope() const { return scope_; } ZoneList* body() const { return body_; } void set_function_token_position(int pos) { function_token_position_ = pos; } @@ -2336,35 +2336,13 @@ class FunctionLiteral V8_FINAL : public Expression { void InitializeSharedInfo(Handle code); Handle debug_name() const { - if (raw_name_ != NULL && !raw_name_->IsEmpty()) { - return raw_name_->string(); - } + if (name_->length() > 0) return name_; return inferred_name(); } - Handle inferred_name() const { - if (!inferred_name_.is_null()) { - ASSERT(raw_inferred_name_ == NULL); - return inferred_name_; - } - if (raw_inferred_name_ != NULL) { - return raw_inferred_name_->string(); - } - UNREACHABLE(); - return Handle(); - } - - // Only one of {set_inferred_name, set_raw_inferred_name} should be called. + Handle inferred_name() const { return inferred_name_; } void set_inferred_name(Handle inferred_name) { inferred_name_ = inferred_name; - ASSERT(raw_inferred_name_== NULL || raw_inferred_name_->IsEmpty()); - raw_inferred_name_ = NULL; - } - - void set_raw_inferred_name(const AstString* raw_inferred_name) { - raw_inferred_name_ = raw_inferred_name; - ASSERT(inferred_name_.is_null()); - inferred_name_ = Handle(); } // shared_info may be null if it's not cached in full code. @@ -2411,8 +2389,7 @@ class FunctionLiteral V8_FINAL : public Expression { protected: FunctionLiteral(Zone* zone, - const AstString* name, - AstValueFactory* ast_value_factory, + Handle name, Scope* scope, ZoneList* body, int materialized_literal_count, @@ -2426,10 +2403,10 @@ class FunctionLiteral V8_FINAL : public Expression { IsGeneratorFlag is_generator, int position) : Expression(zone, position), - raw_name_(name), + name_(name), scope_(scope), body_(body), - raw_inferred_name_(ast_value_factory->empty_string()), + inferred_name_(zone->isolate()->factory()->empty_string()), dont_optimize_reason_(kNoReason), materialized_literal_count_(materialized_literal_count), expected_property_count_(expected_property_count), @@ -2447,12 +2424,10 @@ class FunctionLiteral V8_FINAL : public Expression { } private: - const AstString* raw_name_; Handle name_; Handle shared_info_; Scope* scope_; ZoneList* body_; - const AstString* raw_inferred_name_; Handle inferred_name_; AstProperties ast_properties_; BailoutReason dont_optimize_reason_; @@ -2478,16 +2453,16 @@ class NativeFunctionLiteral V8_FINAL : public Expression { public: DECLARE_NODE_TYPE(NativeFunctionLiteral) - Handle name() const { return name_->string(); } + Handle name() const { return name_; } v8::Extension* extension() const { return extension_; } protected: - NativeFunctionLiteral(Zone* zone, const AstString* name, - v8::Extension* extension, int pos) + NativeFunctionLiteral( + Zone* zone, Handle name, v8::Extension* extension, int pos) : Expression(zone, pos), name_(name), extension_(extension) {} private: - const AstString* name_; + Handle name_; v8::Extension* extension_; }; @@ -2979,8 +2954,7 @@ class AstNullVisitor BASE_EMBEDDED { template class AstNodeFactory V8_FINAL BASE_EMBEDDED { public: - explicit AstNodeFactory(Zone* zone, AstValueFactory* ast_value_factory) - : zone_(zone), ast_value_factory_(ast_value_factory) {} + explicit AstNodeFactory(Zone* zone) : zone_(zone) { } Visitor* visitor() { return &visitor_; } @@ -3044,8 +3018,8 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { VISIT_AND_RETURN(ModuleVariable, module) } - ModulePath* NewModulePath(Module* origin, const AstString* name, int pos) { - ModulePath* module = new (zone_) ModulePath(zone_, origin, name, pos); + ModulePath* NewModulePath(Module* origin, Handle name, int pos) { + ModulePath* module = new(zone_) ModulePath(zone_, origin, name, pos); VISIT_AND_RETURN(ModulePath, module) } @@ -3054,7 +3028,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { VISIT_AND_RETURN(ModuleUrl, module) } - Block* NewBlock(ZoneList* labels, + Block* NewBlock(ZoneStringList* labels, int capacity, bool is_initializer_block, int pos) { @@ -3064,7 +3038,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { } #define STATEMENT_WITH_LABELS(NodeType) \ - NodeType* New##NodeType(ZoneList* labels, int pos) { \ + NodeType* New##NodeType(ZoneStringList* labels, int pos) { \ NodeType* stmt = new(zone_) NodeType(zone_, labels, pos); \ VISIT_AND_RETURN(NodeType, stmt); \ } @@ -3075,7 +3049,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { #undef STATEMENT_WITH_LABELS ForEachStatement* NewForEachStatement(ForEachStatement::VisitMode visit_mode, - ZoneList* labels, + ZoneStringList* labels, int pos) { switch (visit_mode) { case ForEachStatement::ENUMERATE: { @@ -3172,59 +3146,14 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { VISIT_AND_RETURN(CaseClause, clause) } - Literal* NewStringLiteral(const AstString* string, int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewString(string), pos); - VISIT_AND_RETURN(Literal, lit) - } - - // A JavaScript symbol (ECMA-262 edition 6). - Literal* NewSymbolLiteral(const char* name, int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewSymbol(name), pos); + Literal* NewLiteral(Handle handle, int pos) { + Literal* lit = new(zone_) Literal(zone_, handle, pos); VISIT_AND_RETURN(Literal, lit) } Literal* NewNumberLiteral(double number, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewNumber(number), pos); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewSmiLiteral(int number, int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewSmi(number), pos); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewBooleanLiteral(bool b, int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewBoolean(b), pos); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewStringListLiteral(ZoneList* strings, int pos) { - Literal* lit = new (zone_) - Literal(zone_, ast_value_factory_->NewStringList(strings), pos); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewNullLiteral(int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewNull(), pos); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewUndefinedLiteral(int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewUndefined(), pos); - VISIT_AND_RETURN(Literal, lit) - } - - Literal* NewTheHoleLiteral(int pos) { - Literal* lit = - new (zone_) Literal(zone_, ast_value_factory_->NewTheHole(), pos); - VISIT_AND_RETURN(Literal, lit) + return NewLiteral( + zone_->isolate()->factory()->NewNumber(number, TENURED), pos); } ObjectLiteral* NewObjectLiteral( @@ -3241,8 +3170,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { ObjectLiteral::Property* NewObjectLiteralProperty(Literal* key, Expression* value) { - return new (zone_) - ObjectLiteral::Property(zone_, ast_value_factory_, key, value); + return new(zone_) ObjectLiteral::Property(zone_, key, value); } ObjectLiteral::Property* NewObjectLiteralProperty(bool is_getter, @@ -3250,12 +3178,12 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { int pos) { ObjectLiteral::Property* prop = new(zone_) ObjectLiteral::Property(zone_, is_getter, value); - prop->set_key(NewStringLiteral(value->raw_name(), pos)); + prop->set_key(NewLiteral(value->name(), pos)); return prop; // Not an AST node, will not be visited. } - RegExpLiteral* NewRegExpLiteral(const AstString* pattern, - const AstString* flags, + RegExpLiteral* NewRegExpLiteral(Handle pattern, + Handle flags, int literal_index, int pos) { RegExpLiteral* lit = @@ -3277,7 +3205,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { VISIT_AND_RETURN(VariableProxy, proxy) } - VariableProxy* NewVariableProxy(const AstString* name, + VariableProxy* NewVariableProxy(Handle name, bool is_this, Interface* interface = Interface::NewValue(), int position = RelocInfo::kNoPosition) { @@ -3305,7 +3233,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { VISIT_AND_RETURN(CallNew, call) } - CallRuntime* NewCallRuntime(const AstString* name, + CallRuntime* NewCallRuntime(Handle name, const Runtime::Function* function, ZoneList* arguments, int pos) { @@ -3383,8 +3311,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { } FunctionLiteral* NewFunctionLiteral( - const AstString* name, - AstValueFactory* ast_value_factory, + Handle name, Scope* scope, ZoneList* body, int materialized_literal_count, @@ -3398,7 +3325,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { FunctionLiteral::IsGeneratorFlag is_generator, int position) { FunctionLiteral* lit = new(zone_) FunctionLiteral( - zone_, name, ast_value_factory, scope, body, + zone_, name, scope, body, materialized_literal_count, expected_property_count, handler_count, parameter_count, function_type, has_duplicate_parameters, is_function, is_parenthesized, is_generator, position); @@ -3410,8 +3337,7 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { } NativeFunctionLiteral* NewNativeFunctionLiteral( - const AstString* name, v8::Extension* extension, - int pos) { + Handle name, v8::Extension* extension, int pos) { NativeFunctionLiteral* lit = new(zone_) NativeFunctionLiteral(zone_, name, extension, pos); VISIT_AND_RETURN(NativeFunctionLiteral, lit) @@ -3427,7 +3353,6 @@ class AstNodeFactory V8_FINAL BASE_EMBEDDED { private: Zone* zone_; Visitor visitor_; - AstValueFactory* ast_value_factory_; }; diff --git a/src/compiler.cc b/src/compiler.cc index a68c2f893..42fcc7840 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -38,9 +38,7 @@ CompilationInfo::CompilationInfo(Handle