Added support functions for using Literal keys in a HashMap.

This is a preparatory step for using the HashMap clas with Literal keys in the
full code generator. It removes some duplicated code already and removes the
need for 2 HashMaps at each use, which was overly complicated.

Removed one dead function on the way.

Review URL: https://chromiumcodereview.appspot.com/9639011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10973 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
svenpanne@chromium.org 2012-03-09 08:34:35 +00:00
parent ab86e03a05
commit 0b2632fae8
3 changed files with 45 additions and 96 deletions

View File

@ -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<Object> handle = literal->handle();
if (handle->IsNull()) {
continue;
}
uint32_t hash;
ZoneHashMap* table;
void* key;
Factory* factory = Isolate::Current()->factory();
if (handle->IsSymbol()) {
Handle<String> name(String::cast(*handle));
if (name->AsArrayIndex(&hash)) {
Handle<Object> 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<char> buffer(arr, ARRAY_SIZE(arr));
const char* str = DoubleToCString(num, buffer);
Handle<String> 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) {
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(key, hash, true);
table.Lookup(literal, hash, true);
}
}
}
@ -1168,4 +1134,22 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
}
}
Handle<String> Literal::ToString() {
if (handle_->IsString()) return Handle<String>::cast(handle_);
ASSERT(handle_->IsNumber());
char arr[100];
Vector<char> 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

View File

@ -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<Object> 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<String> s1 = static_cast<Literal*>(literal1)->ToString();
Handle<String> s2 = static_cast<Literal*>(literal2)->ToString();
return s1->Equals(*s2);
}
protected:
template<class> friend class AstNodeFactory;
@ -1256,6 +1261,8 @@ class Literal: public Expression {
handle_(handle) { }
private:
Handle<String> ToString();
Handle<Object> handle_;
};

View File

@ -3899,17 +3899,11 @@ Handle<Object> 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<Object> handle = lit->handle();
uint32_t hash;
HashMap* map;
void* key;
if (handle->IsSymbol()) {
Handle<String> name(String::cast(*handle));
if (name->AsArrayIndex(&hash)) {
Handle<Object> 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<char> buffer(arr, ARRAY_SIZE(arr));
const char* str = DoubleToCString(num, buffer);
Handle<String> 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<intptr_t> (entry->value);
intptr_t curr = GetPropertyKind(property);