diff --git a/src/ast.cc b/src/ast.cc index 7fe02be5d8..239e5d0ffe 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -243,55 +243,21 @@ bool IsEqualNumber(void* first, void* second) { void ObjectLiteral::CalculateEmitStore() { - ZoneHashMap properties(&IsEqualString); - ZoneHashMap elements(&IsEqualNumber); - for (int i = this->properties()->length() - 1; i >= 0; i--) { - ObjectLiteral::Property* property = this->properties()->at(i); + ZoneHashMap table(Literal::Match); + for (int i = properties()->length() - 1; i >= 0; i--) { + ObjectLiteral::Property* property = properties()->at(i); Literal* literal = property->key(); - Handle handle = literal->handle(); - - if (handle->IsNull()) { - continue; - } - - uint32_t hash; - ZoneHashMap* table; - void* key; - Factory* factory = Isolate::Current()->factory(); - if (handle->IsSymbol()) { - Handle name(String::cast(*handle)); - if (name->AsArrayIndex(&hash)) { - Handle key_handle = factory->NewNumberFromUint(hash); - key = key_handle.location(); - table = &elements; - } else { - key = name.location(); - hash = name->Hash(); - table = &properties; - } - } else if (handle->ToArrayIndex(&hash)) { - key = handle.location(); - table = &elements; - } else { - ASSERT(handle->IsNumber()); - double num = handle->Number(); - char arr[100]; - Vector buffer(arr, ARRAY_SIZE(arr)); - const char* str = DoubleToCString(num, buffer); - Handle name = factory->NewStringFromAscii(CStrVector(str)); - key = name.location(); - hash = name->Hash(); - table = &properties; - } + if (literal->handle()->IsNull()) continue; + uint32_t hash = literal->Hash(); // If the key of a computed property is in the table, do not emit // a store for the property later. - if (property->kind() == ObjectLiteral::Property::COMPUTED) { - if (table->Lookup(key, hash, false) != NULL) { - property->set_emit_store(false); - } + if (property->kind() == ObjectLiteral::Property::COMPUTED && + table.Lookup(literal, hash, false) != NULL) { + property->set_emit_store(false); + } else { + // Add key to the table. + table.Lookup(literal, hash, true); } - // Add key to the table. - table->Lookup(key, hash, true); } } @@ -1168,4 +1134,22 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) { } } + +Handle Literal::ToString() { + if (handle_->IsString()) return Handle::cast(handle_); + ASSERT(handle_->IsNumber()); + char arr[100]; + Vector buffer(arr, ARRAY_SIZE(arr)); + const char* str; + if (handle_->IsSmi()) { + // Optimization only, the heap number case would subsume this. + OS::SNPrintF(buffer, "%d", Smi::cast(*handle_)->value()); + str = arr; + } else { + str = DoubleToCString(handle_->Number(), buffer); + } + return FACTORY->NewStringFromAscii(CStrVector(str)); +} + + } } // namespace v8::internal diff --git a/src/ast.h b/src/ast.h index 3342de479b..09864885e9 100644 --- a/src/ast.h +++ b/src/ast.h @@ -1211,11 +1211,6 @@ class Literal: public Expression { public: DECLARE_NODE_TYPE(Literal) - // Check if this literal is identical to the other literal. - bool IsIdenticalTo(const Literal* other) const { - return handle_.is_identical_to(other->handle_); - } - virtual bool IsPropertyName() { if (handle_->IsSymbol()) { uint32_t ignored; @@ -1248,6 +1243,16 @@ class Literal: public Expression { Handle handle() const { return handle_; } + // Support for using Literal as a HashMap key. NOTE: Currently, this works + // only for string and number literals! + uint32_t Hash() { return ToString()->Hash(); } + + static bool Match(void* literal1, void* literal2) { + Handle s1 = static_cast(literal1)->ToString(); + Handle s2 = static_cast(literal2)->ToString(); + return s1->Equals(*s2); + } + protected: template friend class AstNodeFactory; @@ -1256,6 +1261,8 @@ class Literal: public Expression { handle_(handle) { } private: + Handle ToString(); + Handle handle_; }; diff --git a/src/parser.cc b/src/parser.cc index a253854d6e..ca8cbb9029 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -3899,17 +3899,11 @@ Handle Parser::GetBoilerplateValue(Expression* expression) { return isolate()->factory()->undefined_value(); } -// Defined in ast.cc -bool IsEqualString(void* first, void* second); -bool IsEqualNumber(void* first, void* second); - - // Validation per 11.1.5 Object Initialiser class ObjectLiteralPropertyChecker { public: ObjectLiteralPropertyChecker(Parser* parser, LanguageMode language_mode) : - props(&IsEqualString), - elems(&IsEqualNumber), + props_(Literal::Match), parser_(parser), language_mode_(language_mode) { } @@ -3938,8 +3932,7 @@ class ObjectLiteralPropertyChecker { } } - HashMap props; - HashMap elems; + HashMap props_; Parser* parser_; LanguageMode language_mode_; }; @@ -3949,44 +3942,9 @@ void ObjectLiteralPropertyChecker::CheckProperty( ObjectLiteral::Property* property, Scanner::Location loc, bool* ok) { - ASSERT(property != NULL); - - Literal* lit = property->key(); - Handle handle = lit->handle(); - - uint32_t hash; - HashMap* map; - void* key; - - if (handle->IsSymbol()) { - Handle name(String::cast(*handle)); - if (name->AsArrayIndex(&hash)) { - Handle key_handle = FACTORY->NewNumberFromUint(hash); - key = key_handle.location(); - map = &elems; - } else { - key = handle.location(); - hash = name->Hash(); - map = &props; - } - } else if (handle->ToArrayIndex(&hash)) { - key = handle.location(); - map = &elems; - } else { - ASSERT(handle->IsNumber()); - double num = handle->Number(); - char arr[100]; - Vector buffer(arr, ARRAY_SIZE(arr)); - const char* str = DoubleToCString(num, buffer); - Handle name = FACTORY->NewStringFromAscii(CStrVector(str)); - key = name.location(); - hash = name->Hash(); - map = &props; - } - - // Lookup property previously defined, if any. - HashMap::Entry* entry = map->Lookup(key, hash, true); + Literal* literal = property->key(); + HashMap::Entry* entry = props_.Lookup(literal, literal->Hash(), true); intptr_t prev = reinterpret_cast (entry->value); intptr_t curr = GetPropertyKind(property);