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:
parent
ab86e03a05
commit
0b2632fae8
72
src/ast.cc
72
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<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
|
||||
|
17
src/ast.h
17
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<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_;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user