Object* k = *key->handle();
if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
kind_ = PROTOTYPE;
+ } else if (value_->AsObjectLiteral() != NULL) {
+ kind_ = OBJECT_LITERAL;
} else {
kind_ = value_->AsLiteral() == NULL ? COMPUTED : CONSTANT;
}
virtual BinaryOperation* AsBinaryOperation() { return NULL; }
virtual Assignment* AsAssignment() { return NULL; }
virtual FunctionLiteral* AsFunctionLiteral() { return NULL; }
+ virtual ObjectLiteral* AsObjectLiteral() { return NULL; }
void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
int statement_pos() const { return statement_pos_; }
public:
enum Kind {
- CONSTANT, // Property with constant value (at compile time).
- COMPUTED, // Property with computed value (at execution time).
+ CONSTANT, // Property with constant value (at compile time).
+ COMPUTED, // Property with computed value (at execution time).
+ OBJECT_LITERAL, // Property value is an object literal.
GETTER, SETTER, // Property is an accessor function.
- PROTOTYPE // Property is __proto__.
+ PROTOTYPE // Property is __proto__.
};
Property(Literal* key, Expression* value);
ObjectLiteral(Handle<FixedArray> constant_properties,
ZoneList<Property*>* properties,
- int literal_index)
+ int literal_index,
+ bool is_simple)
: MaterializedLiteral(literal_index),
constant_properties_(constant_properties),
- properties_(properties) {
+ properties_(properties),
+ is_simple_(is_simple) {
}
+ virtual ObjectLiteral* AsObjectLiteral() { return this; }
virtual void Accept(AstVisitor* v);
Handle<FixedArray> constant_properties() const {
}
ZoneList<Property*>* properties() const { return properties_; }
+ // An object literal is simple if the values consist of only
+ // constants and simple object literals.
+ bool is_simple() const { return is_simple_; }
+
private:
Handle<FixedArray> constant_properties_;
ZoneList<Property*>* properties_;
+ bool is_simple_;
};
for (int i = 0; i < node->properties()->length(); i++) {
ObjectLiteral::Property* property = node->properties()->at(i);
switch (property->kind()) {
- case ObjectLiteral::Property::CONSTANT: break;
+ case ObjectLiteral::Property::CONSTANT:
+ break;
+ case ObjectLiteral::Property::OBJECT_LITERAL:
+ if (property->value()->AsObjectLiteral()->is_simple()) break;
case ObjectLiteral::Property::COMPUTED: {
Handle<Object> key(property->key()->handle());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
// Decide if a property should be the object boilerplate.
bool IsBoilerplateProperty(ObjectLiteral::Property* property);
- // If the property is CONSTANT type, it returns the literal value,
- // otherwise, it return undefined literal as the placeholder
+ // If the property is CONSTANT type, return the literal value;
+ // if the property is OBJECT_LITERAL and the object literal is
+ // simple return a fixed array containing the keys and values of the
+ // object literal.
+ // Otherwise, return undefined literal as the placeholder
// in the object literal boilerplate.
- Literal* GetBoilerplateValue(ObjectLiteral::Property* property);
+ Handle<Object> GetBoilerplateValue(ObjectLiteral::Property* property);
enum FunctionLiteralType {
EXPRESSION,
}
-Literal* Parser::GetBoilerplateValue(ObjectLiteral::Property* property) {
+Handle<Object> Parser::GetBoilerplateValue(ObjectLiteral::Property* property) {
if (property->kind() == ObjectLiteral::Property::CONSTANT)
- return property->value()->AsLiteral();
- return GetLiteralUndefined();
+ return property->value()->AsLiteral()->handle();
+ if (property->kind() == ObjectLiteral::Property::OBJECT_LITERAL) {
+ ObjectLiteral* object_literal = property->value()->AsObjectLiteral();
+ if (object_literal->is_simple()) {
+ return object_literal->constant_properties();
+ }
+ }
+ return Factory::undefined_value();
}
Handle<FixedArray> constant_properties =
Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
int position = 0;
+ bool is_simple = true;
for (int i = 0; i < properties.length(); i++) {
ObjectLiteral::Property* property = properties.at(i);
- if (!IsBoilerplateProperty(property)) continue;
+ if (!IsBoilerplateProperty(property)) {
+ is_simple = false;
+ continue;
+ }
// Add CONSTANT and COMPUTED properties to boilerplate. Use undefined
// value for COMPUTED properties, the real value is filled in at
// runtime. The enumeration order is maintained.
Handle<Object> key = property->key()->handle();
- Literal* literal = GetBoilerplateValue(property);
+ Handle<Object> value = GetBoilerplateValue(property);
+ is_simple = is_simple && !value->IsUndefined();
// Add name, value pair to the fixed array.
constant_properties->set(position++, *key);
- constant_properties->set(position++, *literal->handle());
+ constant_properties->set(position++, *value);
}
return new ObjectLiteral(constant_properties,
properties.elements(),
- literal_index);
+ literal_index,
+ is_simple);
}
}
-static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
- HandleScope scope;
- ASSERT(args.length() == 3);
- // Copy the arguments.
- Handle<FixedArray> literals = args.at<FixedArray>(0);
- int literals_index = Smi::cast(args[1])->value();
- Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
-
+static Handle<Object> CreateObjectLiteralBoilerplate(
+ Handle<FixedArray> literals,
+ Handle<FixedArray> constant_properties) {
// Get the global context from the literals array. This is the
// context in which the function was created and we use the object
// function from this context to create the object literal. We do
for (int index = 0; index < length; index +=2) {
Handle<Object> key(constant_properties->get(index+0));
Handle<Object> value(constant_properties->get(index+1));
+ if (value->IsFixedArray()) {
+ // The value contains the constant_properties of a
+ // simple object literal.
+ Handle<FixedArray> array = Handle<FixedArray>::cast(value);
+ value = CreateObjectLiteralBoilerplate(literals, array);
+ }
Handle<Object> result;
uint32_t element_index = 0;
if (key->IsSymbol()) {
// exception, the exception is converted to an empty handle in
// the handle based operations. In that case, we need to
// convert back to an exception.
- if (result.is_null()) return Failure::Exception();
+ if (result.is_null()) return result;
}
}
+ return boilerplate;
+}
+
+
+static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
+ HandleScope scope;
+ ASSERT(args.length() == 3);
+ // Copy the arguments.
+ Handle<FixedArray> literals = args.at<FixedArray>(0);
+ int literals_index = Smi::cast(args[1])->value();
+ Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
+
+ Handle<Object> result =
+ CreateObjectLiteralBoilerplate(literals, constant_properties);
+
+ if (result.is_null()) return Failure::Exception();
+
// Update the functions literal and return the boilerplate.
- literals->set(literals_index, *boilerplate);
+ literals->set(literals_index, *result);;
- return *boilerplate;
+ return *result;
}
--- /dev/null
+// Copyright 2009 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.
+
+var obj = {
+ a: 7,
+ b: { x: 12, y: 24 },
+ c: 'Zebra'
+}
+
+assertEquals(7, obj.a);
+assertEquals(12, obj.b.x);
+assertEquals(24, obj.b.y);
+assertEquals('Zebra', obj.c);
+
+var z = 24;
+
+var obj2 = {
+ a: 7,
+ b: { x: 12, y: z },
+ c: 'Zebra'
+}
+
+assertEquals(7, obj2.a);
+assertEquals(12, obj2.b.x);
+assertEquals(24, obj2.b.y);
+assertEquals('Zebra', obj2.c);
+
+var arr = [];
+for (var i = 0; i < 2; i++) {
+ arr[i] = {
+ a: 7,
+ b: { x: 12, y: 24 },
+ c: 'Zebra'
+ }
+}
+
+arr[0].a = 2;
+assertEquals(2, arr[0].a);
+assertEquals(7, arr[1].a);