Commit a8c50151 authored by olehougaard's avatar olehougaard

Reapply revisions 1432, 1433, 1469 and 1472 while fixing issue 279.

Review URL: http://codereview.chromium.org/48006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@1571 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 3355c813
......@@ -135,8 +135,12 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
Object* k = *key->handle();
if (k->IsSymbol() && Heap::Proto_symbol()->Equals(String::cast(k))) {
kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL;
} else if (value_->AsLiteral() != NULL) {
kind_ = CONSTANT;
} else {
kind_ = value_->AsLiteral() == NULL ? COMPUTED : CONSTANT;
kind_ = COMPUTED;
}
}
......
......@@ -95,6 +95,7 @@ namespace v8 { namespace internal {
// Forward declarations
class TargetCollector;
class MaterializedLiteral;
#define DEF_FORWARD_DECLARATION(type) class type;
NODE_LIST(DEF_FORWARD_DECLARATION)
......@@ -129,6 +130,9 @@ class Node: public ZoneObject {
virtual BinaryOperation* AsBinaryOperation() { return NULL; }
virtual Assignment* AsAssignment() { return NULL; }
virtual FunctionLiteral* AsFunctionLiteral() { return NULL; }
virtual MaterializedLiteral* AsMaterializedLiteral() { return NULL; }
virtual ObjectLiteral* AsObjectLiteral() { return NULL; }
virtual ArrayLiteral* AsArrayLiteral() { return NULL; }
void set_statement_pos(int statement_pos) { statement_pos_ = statement_pos; }
int statement_pos() const { return statement_pos_; }
......@@ -636,11 +640,23 @@ class Literal: public Expression {
// Base class for literals that needs space in the corresponding JSFunction.
class MaterializedLiteral: public Expression {
public:
explicit MaterializedLiteral(int literal_index)
: literal_index_(literal_index) {}
explicit MaterializedLiteral(int literal_index, bool is_simple, int depth)
: literal_index_(literal_index), is_simple_(is_simple), depth_(depth) {}
virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
int literal_index() { return literal_index_; }
// A materialized literal is simple if the values consist of only
// constants and simple object and array literals.
bool is_simple() const { return is_simple_; }
int depth() const { return depth_; }
private:
int literal_index_;
bool is_simple_;
int depth_;
};
......@@ -655,10 +671,11 @@ class ObjectLiteral: public MaterializedLiteral {
public:
enum Kind {
CONSTANT, // Property with constant value (at compile time).
COMPUTED, // Property with computed value (at execution time).
GETTER, SETTER, // Property is an accessor function.
PROTOTYPE // Property is __proto__.
CONSTANT, // Property with constant value (compile time).
COMPUTED, // Property with computed value (execution time).
MATERIALIZED_LITERAL, // Property value is a materialized literal.
GETTER, SETTER, // Property is an accessor function.
PROTOTYPE // Property is __proto__.
};
Property(Literal* key, Expression* value);
......@@ -676,12 +693,14 @@ class ObjectLiteral: public MaterializedLiteral {
ObjectLiteral(Handle<FixedArray> constant_properties,
ZoneList<Property*>* properties,
int literal_index)
: MaterializedLiteral(literal_index),
int literal_index,
bool is_simple,
int depth)
: MaterializedLiteral(literal_index, is_simple, depth),
constant_properties_(constant_properties),
properties_(properties) {
}
properties_(properties) {}
virtual ObjectLiteral* AsObjectLiteral() { return this; }
virtual void Accept(AstVisitor* v);
Handle<FixedArray> constant_properties() const {
......@@ -701,7 +720,7 @@ class RegExpLiteral: public MaterializedLiteral {
RegExpLiteral(Handle<String> pattern,
Handle<String> flags,
int literal_index)
: MaterializedLiteral(literal_index),
: MaterializedLiteral(literal_index, false, 1),
pattern_(pattern),
flags_(flags) {}
......@@ -717,14 +736,19 @@ class RegExpLiteral: public MaterializedLiteral {
// An array literal has a literals object that is used
// for minimizing the work when constructing it at runtime.
class ArrayLiteral: public Expression {
class ArrayLiteral: public MaterializedLiteral {
public:
ArrayLiteral(Handle<FixedArray> literals,
ZoneList<Expression*>* values)
: literals_(literals), values_(values) {
}
ZoneList<Expression*>* values,
int literal_index,
bool is_simple,
int depth)
: MaterializedLiteral(literal_index, is_simple, depth),
literals_(literals),
values_(values) {}
virtual void Accept(AstVisitor* v);
virtual ArrayLiteral* AsArrayLiteral() { return this; }
Handle<FixedArray> literals() const { return literals_; }
ZoneList<Expression*>* values() const { return values_; }
......
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-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:
......@@ -2662,7 +2662,7 @@ void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
// This deferred code stub will be used for creating the boilerplate
// by calling Runtime_CreateObjectLiteral.
// by calling Runtime_CreateObjectLiteralBoilerplate.
// Each created boilerplate is stored in the JSFunction and they are
// therefore context dependent.
class DeferredObjectLiteral: public DeferredCode {
......@@ -2684,7 +2684,7 @@ void DeferredObjectLiteral::Generate() {
enter()->Bind();
VirtualFrame::SpilledScope spilled_scope(generator());
// If the entry is undefined we call the runtime system to computed
// If the entry is undefined we call the runtime system to compute
// the literal.
VirtualFrame* frame = generator()->frame();
......@@ -2736,7 +2736,11 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
frame_->EmitPush(r2);
// Clone the boilerplate object.
frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
if (node->depth() == 1) {
clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
}
frame_->CallRuntime(clone_function_id, 1);
frame_->EmitPush(r0); // save the result
// r0: cloned object literal
......@@ -2745,7 +2749,11 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
Literal* key = property->key();
Expression* value = property->value();
switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: break;
case ObjectLiteral::Property::CONSTANT:
break;
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
if (property->value()->AsMaterializedLiteral()->is_simple()) break;
// else fall through
case ObjectLiteral::Property::COMPUTED: // fall through
case ObjectLiteral::Property::PROTOTYPE: {
frame_->EmitPush(r0); // dup the result
......@@ -2782,6 +2790,49 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
}
// This deferred code stub will be used for creating the boilerplate
// by calling Runtime_CreateArrayLiteralBoilerplate.
// Each created boilerplate is stored in the JSFunction and they are
// therefore context dependent.
class DeferredArrayLiteral: public DeferredCode {
public:
DeferredArrayLiteral(CodeGenerator* generator, ArrayLiteral* node)
: DeferredCode(generator), node_(node) {
set_comment("[ DeferredArrayLiteral");
}
virtual void Generate();
private:
ArrayLiteral* node_;
};
void DeferredArrayLiteral::Generate() {
// Argument is passed in r1.
enter()->Bind();
VirtualFrame::SpilledScope spilled_scope(generator());
// If the entry is undefined we call the runtime system to computed
// the literal.
VirtualFrame* frame = generator()->frame();
// Literal array (0).
frame->EmitPush(r1);
// Literal index (1).
__ mov(r0, Operand(Smi::FromInt(node_->literal_index())));
frame->EmitPush(r0);
// Constant properties (2).
__ mov(r0, Operand(node_->literals()));
frame->EmitPush(r0);
Result boilerplate =
frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
__ mov(r2, Operand(boilerplate.reg()));
// Result is returned in r2.
exit_.Jump();
}
void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
#ifdef DEBUG
int original_height = frame_->height();
......@@ -2789,17 +2840,38 @@ void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
VirtualFrame::SpilledScope spilled_scope(this);
Comment cmnt(masm_, "[ ArrayLiteral");
// Call runtime to create the array literal.
__ mov(r0, Operand(node->literals()));
frame_->EmitPush(r0);
// Load the function of this frame.
__ ldr(r0, frame_->Function());
__ ldr(r0, FieldMemOperand(r0, JSFunction::kLiteralsOffset));
frame_->EmitPush(r0);
frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2);
DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
// Push the resulting array literal on the stack.
frame_->EmitPush(r0);
// Retrieve the literal array and check the allocated entry.
// Load the function of this activation.
__ ldr(r1, frame_->Function());
// Load the literals array of the function.
__ ldr(r1, FieldMemOperand(r1, JSFunction::kLiteralsOffset));
// Load the literal at the ast saved index.
int literal_offset =
FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
__ ldr(r2, FieldMemOperand(r1, literal_offset));
// Check whether we need to materialize the object literal boilerplate.
// If so, jump to the deferred code.
__ cmp(r2, Operand(Factory::undefined_value()));
deferred->enter()->Branch(eq);
deferred->BindExit();
// Push the object literal boilerplate.
frame_->EmitPush(r2);
// Clone the boilerplate object.
Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
if (node->depth() == 1) {
clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
}
frame_->CallRuntime(clone_function_id, 1);
frame_->EmitPush(r0); // save the result
// r0: cloned object literal
// Generate code to set the elements in the array that are not
// literals.
......
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2006-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:
......@@ -33,6 +33,7 @@
#include "register-allocator-inl.h"
#include "runtime.h"
#include "scopes.h"
#include "parser.h"
namespace v8 { namespace internal {
......@@ -3532,15 +3533,22 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
// Push the boilerplate object.
frame_->Push(&boilerplate);
// Clone the boilerplate object.
Result clone =
frame_->CallRuntime(Runtime::kCloneObjectLiteralBoilerplate, 1);
Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
if (node->depth() == 1) {
clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
}
Result clone = frame_->CallRuntime(clone_function_id, 1);
// Push the newly cloned literal object as the result.
frame_->Push(&clone);
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::MATERIALIZED_LITERAL:
if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
// else fall through.
case ObjectLiteral::Property::COMPUTED: {
Handle<Object> key(property->key()->handle());
Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
......@@ -3598,59 +3606,126 @@ void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
}
// This deferred code stub will be used for creating the boilerplate
// by calling Runtime_CreateArrayLiteralBoilerplate.
// Each created boilerplate is stored in the JSFunction and they are
// therefore context dependent.
class DeferredArrayLiteral: public DeferredCode {
public:
DeferredArrayLiteral(CodeGenerator* generator,
ArrayLiteral* node)
: DeferredCode(generator), node_(node) {
set_comment("[ DeferredArrayLiteral");
}
virtual void Generate();
private:
ArrayLiteral* node_;
};
void DeferredArrayLiteral::Generate() {
Result literals(generator());
enter()->Bind(&literals);
// Since the entry is undefined we call the runtime system to
// compute the literal.
VirtualFrame* frame = generator()->frame();
// Literal array (0).
frame->Push(&literals);
// Literal index (1).
frame->Push(Smi::FromInt(node_->literal_index()));
// Constant properties (2).
frame->Push(node_->literals());
Result boilerplate =
frame->CallRuntime(Runtime::kCreateArrayLiteralBoilerplate, 3);
exit_.Jump(&boilerplate);
}
void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
Comment cmnt(masm_, "[ ArrayLiteral");
DeferredArrayLiteral* deferred = new DeferredArrayLiteral(this, node);
// Call the runtime to create the array literal.
frame_->Push(node->literals());
// Load the literals array of the current function.
// Retrieve the literals array and check the allocated entry. Begin
// with a writable copy of the function of this activation in a
// register.
frame_->PushFunction();
Result literals = frame_->Pop();
literals.ToRegister();
frame_->Spill(literals.reg()); // Make it writable.
frame_->Spill(literals.reg());
// Load the literals array of the function.
__ mov(literals.reg(),
FieldOperand(literals.reg(), JSFunction::kLiteralsOffset));
frame_->Push(&literals);
Result array = frame_->CallRuntime(Runtime::kCreateArrayLiteral, 2);
// Load the literal at the ast saved index.
int literal_offset =
FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
Result boilerplate = allocator_->Allocate();
ASSERT(boilerplate.is_valid());
__ mov(boilerplate.reg(), FieldOperand(literals.reg(), literal_offset));
// Check whether we need to materialize the object literal boilerplate.
// If so, jump to the deferred code passing the literals array.
__ cmp(boilerplate.reg(), Factory::undefined_value());
deferred->enter()->Branch(equal, &literals, not_taken);
literals.Unuse();
// The deferred code returns the boilerplate object.
deferred->BindExit(&boilerplate);
// Push the resulting array literal on the stack.
frame_->Push(&array);
frame_->Push(&boilerplate);
// Clone the boilerplate object.
Runtime::FunctionId clone_function_id = Runtime::kCloneLiteralBoilerplate;
if (node->depth() == 1) {
clone_function_id = Runtime::kCloneShallowLiteralBoilerplate;
}
Result clone = frame_->CallRuntime(clone_function_id, 1);
// Push the newly cloned literal object as the result.
frame_->Push(&clone);
// Generate code to set the elements in the array that are not
// literals.
for (int i = 0; i < node->values()->length(); i++) {
Expression* value = node->values()->at(i);
// If value is literal the property value is already set in the
// If value is a literal the property value is already set in the
// boilerplate object.
if (value->AsLiteral() == NULL) {
// The property must be set by generated code.
Load(value);
if (value->AsLiteral() != NULL) continue;
// If value is a materialized literal the property value is already set
// in the boilerplate object if it is simple.
if (CompileTimeValue::IsCompileTimeValue(value)) continue;
// Get the property value off the stack.
Result prop_value = frame_->Pop();
prop_value.ToRegister();
// The property must be set by generated code.
Load(value);
// Fetch the array literal while leaving a copy on the stack and
// use it to get the elements array.
frame_->Dup();
Result elements = frame_->Pop();
elements.ToRegister();
frame_->Spill(elements.reg());
// Get the elements array.
__ mov(elements.reg(),
FieldOperand(elements.reg(), JSObject::kElementsOffset));
// Write to the indexed properties array.
int offset = i * kPointerSize + Array::kHeaderSize;
__ mov(FieldOperand(elements.reg(), offset), prop_value.reg());
// Update the write barrier for the array address.
frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
Result scratch = allocator_->Allocate();
ASSERT(scratch.is_valid());
__ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
}
// Get the property value off the stack.
Result prop_value = frame_->Pop();
prop_value.ToRegister();
// Fetch the array literal while leaving a copy on the stack and
// use it to get the elements array.
frame_->Dup();
Result elements = frame_->Pop();
elements.ToRegister();
frame_->Spill(elements.reg());
// Get the elements array.
__ mov(elements.reg(),
FieldOperand(elements.reg(), JSObject::kElementsOffset));
// Write to the indexed properties array.
int offset = i * kPointerSize + Array::kHeaderSize;
__ mov(FieldOperand(elements.reg(), offset), prop_value.reg());
// Update the write barrier for the array address.
frame_->Spill(prop_value.reg()); // Overwritten by the write barrier.
Result scratch = allocator_->Allocate();
ASSERT(scratch.is_valid());
__ RecordWrite(elements.reg(), offset, prop_value.reg(), scratch.reg());
}
}
......
......@@ -167,8 +167,6 @@ namespace v8 { namespace internal {
V(char_at_symbol, "CharAt") \
V(undefined_symbol, "undefined") \
V(value_of_symbol, "valueOf") \
V(CreateObjectLiteralBoilerplate_symbol, "CreateObjectLiteralBoilerplate") \
V(CreateArrayLiteral_symbol, "CreateArrayLiteral") \
V(InitializeVarGlobal_symbol, "InitializeVarGlobal") \
V(InitializeConstGlobal_symbol, "InitializeConstGlobal") \
V(stack_overflow_symbol, "kStackOverflowBoilerplate") \
......
......@@ -1094,6 +1094,15 @@ Object* JSObject::FastPropertyAtPut(int index, Object* value) {
}
Object* JSObject::InObjectPropertyAt(int index) {
// Adjust for the number of properties stored in the object.
index -= map()->inobject_properties();
ASSERT(index < 0);
int offset = map()->instance_size() + (index * kPointerSize);
return READ_FIELD(this, offset);
}
Object* JSObject::InObjectPropertyAtPut(int index,
Object* value,
WriteBarrierMode mode) {
......
......@@ -1396,7 +1396,8 @@ class JSObject: public HeapObject {
inline Object* FastPropertyAt(int index);
inline Object* FastPropertyAtPut(int index, Object* value);
// Access to set in object properties.
// Access to in object properties.
inline Object* InObjectPropertyAt(int index);
inline Object* InObjectPropertyAtPut(int index,
Object* value,
WriteBarrierMode mode
......
......@@ -158,10 +158,12 @@ class Parser {
// 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 expression is a literal, return the literal value;
// if the expression is a materialized literal and is simple return a
// compile time value as encoded by CompileTimeValue::GetValue().
// Otherwise, return undefined literal as the placeholder
// in the object literal boilerplate.
Literal* GetBoilerplateValue(ObjectLiteral::Property* property);
Handle<Object> GetBoilerplateValue(Expression* expression);
enum FunctionLiteralType {
EXPRESSION,
......@@ -3054,6 +3056,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
// Update the scope information before the pre-parsing bailout.
temp_scope_->set_contains_array_literal();
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
if (is_pre_parsing_) return NULL;
......@@ -3062,16 +3065,24 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
Factory::NewFixedArray(values.length(), TENURED);
// Fill in the literals.
bool is_simple = true;
int depth = 1;
for (int i = 0; i < values.length(); i++) {
Literal* literal = values.at(i)->AsLiteral();
if (literal == NULL) {
MaterializedLiteral* m_literal = values.at(i)->AsMaterializedLiteral();
if (m_literal != NULL && m_literal->depth() + 1 > depth) {
depth = m_literal->depth() + 1;
}
Handle<Object> boilerplate_value = GetBoilerplateValue(values.at(i));
if (boilerplate_value->IsUndefined()) {
literals->set_the_hole(i);
is_simple = false;
} else {
literals->set(i, *literal->handle());
literals->set(i, *boilerplate_value);
}
}
return NEW(ArrayLiteral(literals, values.elements()));
return NEW(ArrayLiteral(literals, values.elements(),
literal_index, is_simple, depth));
}
......@@ -3081,10 +3092,48 @@ bool Parser::IsBoilerplateProperty(ObjectLiteral::Property* property) {
}
Literal* Parser::GetBoilerplateValue(ObjectLiteral::Property* property) {
if (property->kind() == ObjectLiteral::Property::CONSTANT)
return property->value()->AsLiteral();
return GetLiteralUndefined();
bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
MaterializedLiteral* lit = expression->AsMaterializedLiteral();
return lit != NULL && lit->is_simple();
}
Handle<FixedArray> CompileTimeValue::GetValue(Expression* expression) {
ASSERT(IsCompileTimeValue(expression));
Handle<FixedArray> result = Factory::NewFixedArray(2, TENURED);
ObjectLiteral* object_literal = expression->AsObjectLiteral();
if (object_literal != NULL) {
ASSERT(object_literal->is_simple());
result->set(kTypeSlot, Smi::FromInt(OBJECT_LITERAL));
result->set(kElementsSlot, *object_literal->constant_properties());
} else {
ArrayLiteral* array_literal = expression->AsArrayLiteral();
ASSERT(array_literal != NULL && array_literal->is_simple());
result->set(kTypeSlot, Smi::FromInt(ARRAY_LITERAL));
result->set(kElementsSlot, *array_literal->literals());
}
return result;
}
CompileTimeValue::Type CompileTimeValue::GetType(Handle<FixedArray> value) {
Smi* type_value = Smi::cast(value->get(kTypeSlot));
return static_cast<Type>(type_value->value());
}
Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
}
Handle<Object> Parser::GetBoilerplateValue(Expression* expression) {
if (expression->AsLiteral() != NULL) {
return expression->AsLiteral()->handle();
}
if (CompileTimeValue::IsCompileTimeValue(expression)) {
return CompileTimeValue::GetValue(expression);
}
return Factory::undefined_value();
}
......@@ -3179,24 +3228,36 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
Handle<FixedArray> constant_properties =
Factory::NewFixedArray(number_of_boilerplate_properties * 2, TENURED);
int position = 0;
bool is_simple = true;
int depth = 1;
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;
}
MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral();
if (m_literal != NULL && m_literal->depth() + 1 > depth) {
depth = m_literal->depth() + 1;
}
// 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->value());
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,
depth);
}
......
......@@ -29,6 +29,7 @@
#define V8_PARSER_H_
#include "scanner.h"
#include "allocation.h"
namespace v8 { namespace internal {
......@@ -165,6 +166,35 @@ FunctionLiteral* MakeLazyAST(Handle<Script> script,
int end_position,
bool is_expression);
// Support for handling complex values (array and object literals) that
// can be fully handled at compile time.
class CompileTimeValue: public AllStatic {
public:
enum Type {
OBJECT_LITERAL,
ARRAY_LITERAL
};
static bool IsCompileTimeValue(Expression* expression);
// Get the value as a compile time value.
static Handle<FixedArray> GetValue(Expression* expression);
// Get the type of a compile time value returned by GetValue().
static Type GetType(Handle<FixedArray> value);
// Get the elements array of a compile time value returned by GetValue().
static Handle<FixedArray> GetElements(Handle<FixedArray> value);
private:
static const int kTypeSlot = 0;
static const int kElementsSlot = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(CompileTimeValue);
};
} } // namespace v8::internal
#endif // V8_PARSER_H_
This diff is collapsed.
......@@ -253,9 +253,10 @@ namespace v8 { namespace internal {
\
/* Literals */ \
F(MaterializeRegExpLiteral, 4)\
F(CreateArrayLiteral, 2) \
F(CreateArrayLiteralBoilerplate, 3) \
F(CreateObjectLiteralBoilerplate, 3) \
F(CloneObjectLiteralBoilerplate, 1) \
F(CloneLiteralBoilerplate, 1) \
F(CloneShallowLiteralBoilerplate, 1) \
\
/* Catch context extension objects */ \
F(CreateCatchExtensionObject, 2) \
......@@ -328,7 +329,6 @@ class Runtime : public AllStatic {
kNofFunctions
#undef F
};
static Object* CreateArrayLiteral(Arguments args);
// Runtime function descriptor.
struct Function {
......
......@@ -121,7 +121,9 @@ var knownProblems = {
"PushContext": true,
"LazyCompile": true,
"CreateObjectLiteralBoilerplate": true,
"CloneObjectLiteralBoilerplate": true,
"CloneLiteralBoilerplate": true,
"CloneShallowLiteralBoilerplate": true,
"CreateArrayLiteralBoilerplate": true,
"IS_VAR": true,
"ResolvePossiblyDirectEval": true,
"Log": true
......
......@@ -58,6 +58,48 @@ for (var i = 0; i < 2; i++) {
}
}
arr[0].a = 2;
assertEquals(2, arr[0].a);
assertEquals(7, arr[1].a);
arr[0].b.x = 2;
assertEquals(2, arr[0].b.x);
assertEquals(12, arr[1].b.x);
function makeSparseArray() {
return {
'0': { x: 12, y: 24 },
'1000000': { x: 0, y: 0 }
};
}
var sa1 = makeSparseArray();
sa1[0].x = 0;
var sa2 = makeSparseArray();
assertEquals(12, sa2[0].x);
// Test that non-constant literals work.
var n = new Object();
function makeNonConstantArray() { return [ [ n ] ]; }
var a = makeNonConstantArray();
a[0][0].foo = "bar";
assertEquals("bar", n.foo);
function makeNonConstantObject() { return { a: { b: n } }; }
a = makeNonConstantObject();
a.a.b.bar = "foo";
assertEquals("foo", n.bar);
// Test that exceptions for regexps still hold.
function makeRegexpInArray() { return [ [ /a*/, {} ] ]; }
a = makeRegexpInArray();
var b = makeRegexpInArray();
assertTrue(a[0][0] === b[0][0]);
assertFalse(a[0][1] === b[0][1]);
function makeRegexpInObject() { return { a: { b: /b*/, c: {} } }; }
a = makeRegexpInObject();
b = makeRegexpInObject();
assertTrue(a.a.b === b.a.b);
assertFalse(a.a.c === b.a.c);
......@@ -50,4 +50,13 @@ function makeObjectInArray() {
a = makeObjectInArray();
a[0].bar = 1;
b = makeObjectInArray();
assertEquals('undefined', typeof(b[0].bar), "Object in object");
assertEquals('undefined', typeof(b[0].bar), "Object in array");
function makeArrayInArray() {
return [ [] ];
}
a = makeArrayInArray();
a[0].push(5);
b = makeArrayInArray();
assertEquals(0, b[0].length, "Array in array");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment