ES6: Add support for method shorthand in object literals

This is governed by the harmony-object-literals flag.

BUG=v8:3516
LOG=Y
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/477263002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23846 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
arv@chromium.org 2014-09-10 16:39:42 +00:00
parent 9261c44fd4
commit 45d8e74cd6
37 changed files with 633 additions and 302 deletions

View File

@ -1332,9 +1332,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ mov(r2, Operand(info)); __ mov(r2, Operand(info));
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -5492,9 +5492,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ mov(r2, Operand(instr->hydrogen()->shared_info())); __ mov(r2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -1318,9 +1318,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ Mov(x2, Operand(info)); __ Mov(x2, Operand(info));
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -2864,9 +2864,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ Mov(x2, Operand(instr->hydrogen()->shared_info())); __ Mov(x2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -2325,12 +2325,6 @@ class FunctionLiteral FINAL : public Expression {
kNotParenthesized kNotParenthesized
}; };
enum KindFlag {
kNormalFunction,
kArrowFunction,
kGeneratorFunction
};
enum ArityRestriction { enum ArityRestriction {
NORMAL_ARITY, NORMAL_ARITY,
GETTER_ARITY, GETTER_ARITY,
@ -2420,8 +2414,16 @@ class FunctionLiteral FINAL : public Expression {
bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized); bitfield_ = IsParenthesized::update(bitfield_, kIsParenthesized);
} }
bool is_generator() { return IsGenerator::decode(bitfield_); } FunctionKind kind() { return FunctionKindBits::decode(bitfield_); }
bool is_arrow() { return IsArrow::decode(bitfield_); } bool is_arrow() {
return IsArrowFunction(FunctionKindBits::decode(bitfield_));
}
bool is_generator() {
return IsGeneratorFunction(FunctionKindBits::decode(bitfield_));
}
bool is_concise_method() {
return IsConciseMethod(FunctionKindBits::decode(bitfield_));
}
int ast_node_count() { return ast_properties_.node_count(); } int ast_node_count() { return ast_properties_.node_count(); }
AstProperties::Flags* flags() { return ast_properties_.flags(); } AstProperties::Flags* flags() { return ast_properties_.flags(); }
@ -2445,7 +2447,7 @@ class FunctionLiteral FINAL : public Expression {
int parameter_count, FunctionType function_type, int parameter_count, FunctionType function_type,
ParameterFlag has_duplicate_parameters, ParameterFlag has_duplicate_parameters,
IsFunctionFlag is_function, IsFunctionFlag is_function,
IsParenthesizedFlag is_parenthesized, KindFlag kind, IsParenthesizedFlag is_parenthesized, FunctionKind kind,
int position, IdGen* id_gen) int position, IdGen* id_gen)
: Expression(zone, position, id_gen), : Expression(zone, position, id_gen),
raw_name_(name), raw_name_(name),
@ -2464,8 +2466,8 @@ class FunctionLiteral FINAL : public Expression {
HasDuplicateParameters::encode(has_duplicate_parameters) | HasDuplicateParameters::encode(has_duplicate_parameters) |
IsFunction::encode(is_function) | IsFunction::encode(is_function) |
IsParenthesized::encode(is_parenthesized) | IsParenthesized::encode(is_parenthesized) |
IsGenerator::encode(kind == kGeneratorFunction) | FunctionKindBits::encode(kind);
IsArrow::encode(kind == kArrowFunction); DCHECK(IsValidFunctionKind(kind));
} }
private: private:
@ -2486,14 +2488,13 @@ class FunctionLiteral FINAL : public Expression {
int function_token_position_; int function_token_position_;
unsigned bitfield_; unsigned bitfield_;
class IsExpression: public BitField<bool, 0, 1> {}; class IsExpression : public BitField<bool, 0, 1> {};
class IsAnonymous: public BitField<bool, 1, 1> {}; class IsAnonymous : public BitField<bool, 1, 1> {};
class Pretenure: public BitField<bool, 2, 1> {}; class Pretenure : public BitField<bool, 2, 1> {};
class HasDuplicateParameters: public BitField<ParameterFlag, 3, 1> {}; class HasDuplicateParameters : public BitField<ParameterFlag, 3, 1> {};
class IsFunction: public BitField<IsFunctionFlag, 4, 1> {}; class IsFunction : public BitField<IsFunctionFlag, 4, 1> {};
class IsParenthesized: public BitField<IsParenthesizedFlag, 5, 1> {}; class IsParenthesized : public BitField<IsParenthesizedFlag, 5, 1> {};
class IsGenerator : public BitField<bool, 6, 1> {}; class FunctionKindBits : public BitField<FunctionKind, 6, 3> {};
class IsArrow : public BitField<bool, 7, 1> {};
}; };
@ -3439,8 +3440,8 @@ class AstNodeFactory FINAL BASE_EMBEDDED {
FunctionLiteral::ParameterFlag has_duplicate_parameters, FunctionLiteral::ParameterFlag has_duplicate_parameters,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
FunctionLiteral::IsFunctionFlag is_function, FunctionLiteral::IsFunctionFlag is_function,
FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
FunctionLiteral::KindFlag kind, int position) { int position) {
FunctionLiteral* lit = new (zone_) FunctionLiteral( FunctionLiteral* lit = new (zone_) FunctionLiteral(
zone_, name, ast_value_factory, scope, body, materialized_literal_count, zone_, name, ast_value_factory, scope, body, materialized_literal_count,
expected_property_count, handler_count, parameter_count, function_type, expected_property_count, handler_count, parameter_count, function_type,

View File

@ -1343,7 +1343,7 @@ HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
NOT_TENURED, JS_FUNCTION_TYPE); NOT_TENURED, JS_FUNCTION_TYPE);
int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(), int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(),
casted_stub()->is_generator()); casted_stub()->kind());
// Compute the function map in the current native context and set that // Compute the function map in the current native context and set that
// as the map of the allocated object. // as the map of the allocated object.

View File

@ -551,21 +551,27 @@ class NumberToStringStub FINAL : public HydrogenCodeStub {
class FastNewClosureStub : public HydrogenCodeStub { class FastNewClosureStub : public HydrogenCodeStub {
public: public:
FastNewClosureStub(Isolate* isolate, StrictMode strict_mode, FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
bool is_generator) FunctionKind kind)
: HydrogenCodeStub(isolate) { : HydrogenCodeStub(isolate) {
DCHECK(IsValidFunctionKind(kind));
set_sub_minor_key(StrictModeBits::encode(strict_mode) | set_sub_minor_key(StrictModeBits::encode(strict_mode) |
IsGeneratorBits::encode(is_generator)); FunctionKindBits::encode(kind));
} }
StrictMode strict_mode() const { StrictMode strict_mode() const {
return StrictModeBits::decode(sub_minor_key()); return StrictModeBits::decode(sub_minor_key());
} }
bool is_generator() const { return IsGeneratorBits::decode(sub_minor_key()); } FunctionKind kind() const {
return FunctionKindBits::decode(sub_minor_key());
}
bool is_arrow() const { return IsArrowFunction(kind()); }
bool is_generator() const { return IsGeneratorFunction(kind()); }
bool is_concise_method() const { return IsConciseMethod(kind()); }
private: private:
class StrictModeBits : public BitField<StrictMode, 0, 1> {}; class StrictModeBits : public BitField<StrictMode, 0, 1> {};
class IsGeneratorBits : public BitField<bool, 1, 1> {}; class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure); DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub); DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);

View File

@ -654,8 +654,7 @@ static void SetFunctionInfo(Handle<SharedFunctionInfo> function_info,
function_info->set_is_function(lit->is_function()); function_info->set_is_function(lit->is_function());
function_info->set_bailout_reason(lit->dont_optimize_reason()); function_info->set_bailout_reason(lit->dont_optimize_reason());
function_info->set_dont_cache(lit->flags()->Contains(kDontCache)); function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
function_info->set_is_generator(lit->is_generator()); function_info->set_kind(lit->kind());
function_info->set_is_arrow(lit->is_arrow());
} }
@ -871,9 +870,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
// Allocate function. // Allocate function.
DCHECK(!info->code().is_null()); DCHECK(!info->code().is_null());
result = isolate->factory()->NewSharedFunctionInfo( result = isolate->factory()->NewSharedFunctionInfo(
lit->name(), lit->materialized_literal_count(), lit->is_generator(), lit->name(), lit->materialized_literal_count(), lit->kind(),
lit->is_arrow(), info->code(), info->code(), ScopeInfo::Create(info->scope(), info->zone()),
ScopeInfo::Create(info->scope(), info->zone()),
info->feedback_vector()); info->feedback_vector());
DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position()); DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
@ -1094,9 +1092,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
// Create a shared function info object. // Create a shared function info object.
Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo( Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
literal->name(), literal->materialized_literal_count(), literal->name(), literal->materialized_literal_count(), literal->kind(),
literal->is_generator(), literal->is_arrow(), info.code(), scope_info, info.code(), scope_info, info.feedback_vector());
info.feedback_vector());
SetFunctionInfo(result, literal, false, script); SetFunctionInfo(result, literal, false, script);
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
result->set_allows_lazy_compilation(allow_lazy); result->set_allows_lazy_compilation(allow_lazy);

View File

@ -553,14 +553,20 @@ class Context: public FixedArray {
return kHeaderSize + index * kPointerSize - kHeapObjectTag; return kHeaderSize + index * kPointerSize - kHeapObjectTag;
} }
static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) { static int FunctionMapIndex(StrictMode strict_mode, FunctionKind kind) {
return is_generator if (IsGeneratorFunction(kind)) {
? (strict_mode == SLOPPY return strict_mode == SLOPPY ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX : STRICT_GENERATOR_FUNCTION_MAP_INDEX;
: STRICT_GENERATOR_FUNCTION_MAP_INDEX) }
: (strict_mode == SLOPPY
? SLOPPY_FUNCTION_MAP_INDEX if (IsConciseMethod(kind)) {
: STRICT_FUNCTION_MAP_INDEX); return strict_mode == SLOPPY
? SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX
: STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX;
}
return strict_mode == SLOPPY ? SLOPPY_FUNCTION_MAP_INDEX
: STRICT_FUNCTION_MAP_INDEX;
} }
static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize; static const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;

View File

@ -1237,6 +1237,9 @@ void Factory::InitializeFunction(Handle<JSFunction> function,
function->set_prototype_or_initial_map(*the_hole_value()); function->set_prototype_or_initial_map(*the_hole_value());
function->set_literals_or_bindings(*empty_fixed_array()); function->set_literals_or_bindings(*empty_fixed_array());
function->set_next_function_link(*undefined_value()); function->set_next_function_link(*undefined_value());
// TODO(arv): This does not look correct. We need to make sure we use
// a Map that has no prototype property.
if (info->is_arrow()) function->RemovePrototype(); if (info->is_arrow()) function->RemovePrototype();
} }
@ -1356,8 +1359,7 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
Handle<SharedFunctionInfo> info, Handle<SharedFunctionInfo> info,
Handle<Context> context, Handle<Context> context,
PretenureFlag pretenure) { PretenureFlag pretenure) {
int map_index = Context::FunctionMapIndex(info->strict_mode(), int map_index = Context::FunctionMapIndex(info->strict_mode(), info->kind());
info->is_generator());
Handle<Map> map(Map::cast(context->native_context()->get(map_index))); Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
Handle<JSFunction> result = NewFunction(map, info, context, pretenure); Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
@ -1904,13 +1906,14 @@ Handle<FixedArray> Factory::NewTypeFeedbackVector(int slot_count) {
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo( Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name, int number_of_literals, bool is_generator, Handle<String> name, int number_of_literals, FunctionKind kind,
bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info, Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector) { Handle<FixedArray> feedback_vector) {
DCHECK(IsValidFunctionKind(kind));
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code); Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
shared->set_scope_info(*scope_info); shared->set_scope_info(*scope_info);
shared->set_feedback_vector(*feedback_vector); shared->set_feedback_vector(*feedback_vector);
shared->set_is_arrow(is_arrow); shared->set_kind(kind);
int literals_array_size = number_of_literals; int literals_array_size = number_of_literals;
// If the function contains object, regexp or array literals, // If the function contains object, regexp or array literals,
// allocate extra space for a literals array prefix containing the // allocate extra space for a literals array prefix containing the
@ -1919,7 +1922,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
literals_array_size += JSFunction::kLiteralsPrefixSize; literals_array_size += JSFunction::kLiteralsPrefixSize;
} }
shared->set_num_literals(literals_array_size); shared->set_num_literals(literals_array_size);
if (is_generator) { if (IsGeneratorFunction(kind)) {
shared->set_instance_class_name(isolate()->heap()->Generator_string()); shared->set_instance_class_name(isolate()->heap()->Generator_string());
shared->DisableOptimization(kGenerator); shared->DisableOptimization(kGenerator);
} }

View File

@ -598,8 +598,8 @@ class Factory FINAL {
// Allocates a new SharedFunctionInfo object. // Allocates a new SharedFunctionInfo object.
Handle<SharedFunctionInfo> NewSharedFunctionInfo( Handle<SharedFunctionInfo> NewSharedFunctionInfo(
Handle<String> name, int number_of_literals, bool is_generator, Handle<String> name, int number_of_literals, FunctionKind kind,
bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info, Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector); Handle<FixedArray> feedback_vector);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name, Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
MaybeHandle<Code> code); MaybeHandle<Code> code);

View File

@ -161,6 +161,8 @@ DEFINE_BOOL(harmony_strings, false, "enable harmony string")
DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays") DEFINE_BOOL(harmony_arrays, false, "enable harmony arrays")
DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions") DEFINE_BOOL(harmony_arrow_functions, false, "enable harmony arrow functions")
DEFINE_BOOL(harmony_classes, false, "enable harmony classes") DEFINE_BOOL(harmony_classes, false, "enable harmony classes")
DEFINE_BOOL(harmony_object_literals, false,
"enable harmony object literal extensions")
DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)") DEFINE_BOOL(harmony, false, "enable all harmony features (except proxies)")
DEFINE_IMPLICATION(harmony, harmony_scoping) DEFINE_IMPLICATION(harmony, harmony_scoping)
@ -172,6 +174,7 @@ DEFINE_IMPLICATION(harmony, harmony_strings)
DEFINE_IMPLICATION(harmony, harmony_arrays) DEFINE_IMPLICATION(harmony, harmony_arrays)
DEFINE_IMPLICATION(harmony, harmony_arrow_functions) DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
DEFINE_IMPLICATION(harmony, harmony_classes) DEFINE_IMPLICATION(harmony, harmony_classes)
DEFINE_IMPLICATION(harmony, harmony_object_literals)
DEFINE_IMPLICATION(harmony_modules, harmony_scoping) DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
DEFINE_IMPLICATION(harmony, es_staging) DEFINE_IMPLICATION(harmony, es_staging)

View File

@ -1547,11 +1547,9 @@ void FullCodeGenerator::VisitNativeFunctionLiteral(
const int literals = fun->NumberOfLiterals(); const int literals = fun->NumberOfLiterals();
Handle<Code> code = Handle<Code>(fun->shared()->code()); Handle<Code> code = Handle<Code>(fun->shared()->code());
Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub()); Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
bool is_generator = false;
bool is_arrow = false;
Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo> shared =
isolate()->factory()->NewSharedFunctionInfo( isolate()->factory()->NewSharedFunctionInfo(
name, literals, is_generator, is_arrow, code, name, literals, FunctionKind::kNormalFunction, code,
Handle<ScopeInfo>(fun->shared()->scope_info()), Handle<ScopeInfo>(fun->shared()->scope_info()),
Handle<FixedArray>(fun->shared()->feedback_vector())); Handle<FixedArray>(fun->shared()->feedback_vector()));
shared->set_construct_stub(*construct_stub); shared->set_construct_stub(*construct_stub);

View File

@ -756,6 +756,41 @@ enum MinusZeroMode {
FAIL_ON_MINUS_ZERO FAIL_ON_MINUS_ZERO
}; };
enum FunctionKind {
kNormalFunction = 0,
kArrowFunction = 1,
kGeneratorFunction = 2,
kConciseMethod = 4
};
inline bool IsValidFunctionKind(FunctionKind kind) {
// At the moment these are mutually exclusive but in the future that wont be
// the case since ES6 allows concise generator methods.
return kind == FunctionKind::kNormalFunction ||
kind == FunctionKind::kArrowFunction ||
kind == FunctionKind::kGeneratorFunction ||
kind == FunctionKind::kConciseMethod;
}
inline bool IsArrowFunction(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind));
return kind & FunctionKind::kArrowFunction;
}
inline bool IsGeneratorFunction(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind));
return kind & FunctionKind::kGeneratorFunction;
}
inline bool IsConciseMethod(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind));
return kind & FunctionKind::kConciseMethod;
}
} } // namespace v8::internal } } // namespace v8::internal
namespace i = v8::internal; namespace i = v8::internal;

View File

@ -7481,18 +7481,20 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; } Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
bool pretenure() const { return pretenure_; } bool pretenure() const { return pretenure_; }
bool has_no_literals() const { return has_no_literals_; } bool has_no_literals() const { return has_no_literals_; }
bool is_generator() const { return is_generator_; } bool is_arrow() const { return IsArrowFunction(kind_); }
bool is_generator() const { return IsGeneratorFunction(kind_); }
bool is_concise_method() const { return IsConciseMethod(kind_); }
FunctionKind kind() const { return kind_; }
StrictMode strict_mode() const { return strict_mode_; } StrictMode strict_mode() const { return strict_mode_; }
private: private:
HFunctionLiteral(HValue* context, HFunctionLiteral(HValue* context, Handle<SharedFunctionInfo> shared,
Handle<SharedFunctionInfo> shared,
bool pretenure) bool pretenure)
: HTemplateInstruction<1>(HType::JSObject()), : HTemplateInstruction<1>(HType::JSObject()),
shared_info_(shared), shared_info_(shared),
kind_(shared->kind()),
pretenure_(pretenure), pretenure_(pretenure),
has_no_literals_(shared->num_literals() == 0), has_no_literals_(shared->num_literals() == 0),
is_generator_(shared->is_generator()),
strict_mode_(shared->strict_mode()) { strict_mode_(shared->strict_mode()) {
SetOperandAt(0, context); SetOperandAt(0, context);
set_representation(Representation::Tagged()); set_representation(Representation::Tagged());
@ -7502,9 +7504,9 @@ class HFunctionLiteral FINAL : public HTemplateInstruction<1> {
virtual bool IsDeletable() const OVERRIDE { return true; } virtual bool IsDeletable() const OVERRIDE { return true; }
Handle<SharedFunctionInfo> shared_info_; Handle<SharedFunctionInfo> shared_info_;
FunctionKind kind_;
bool pretenure_ : 1; bool pretenure_ : 1;
bool has_no_literals_ : 1; bool has_no_literals_ : 1;
bool is_generator_ : 1;
StrictMode strict_mode_; StrictMode strict_mode_;
}; };

View File

@ -1254,9 +1254,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ mov(ebx, Immediate(info)); __ mov(ebx, Immediate(info));
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -5290,9 +5290,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ mov(ebx, Immediate(instr->hydrogen()->shared_info())); __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -1319,9 +1319,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ li(a2, Operand(info)); __ li(a2, Operand(info));
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -5479,9 +5479,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ li(a2, Operand(instr->hydrogen()->shared_info())); __ li(a2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -1314,9 +1314,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ li(a2, Operand(info)); __ li(a2, Operand(info));
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -5519,9 +5519,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ li(a2, Operand(instr->hydrogen()->shared_info())); __ li(a2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -5559,6 +5559,19 @@ void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
} }
FunctionKind SharedFunctionInfo::kind() {
return FunctionKindBits::decode(compiler_hints());
}
void SharedFunctionInfo::set_kind(FunctionKind kind) {
DCHECK(IsValidFunctionKind(kind));
int hints = compiler_hints();
hints = FunctionKindBits::update(hints, kind);
set_compiler_hints(hints);
}
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin, BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
kInlineBuiltin) kInlineBuiltin)
@ -5570,8 +5583,10 @@ BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_anonymous, kIsAnonymous)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_function, kIsFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_cache, kDontCache)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, dont_flush, kDontFlush)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow) BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_arrow, kIsArrow)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_generator, kIsGenerator)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
kIsConciseMethod)
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset) ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset) ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)

View File

@ -7121,6 +7121,12 @@ class SharedFunctionInfo: public HeapObject {
// Indicates that this function is an arrow function. // Indicates that this function is an arrow function.
DECL_BOOLEAN_ACCESSORS(is_arrow) DECL_BOOLEAN_ACCESSORS(is_arrow)
// Indicates that this function is a concise method.
DECL_BOOLEAN_ACCESSORS(is_concise_method)
inline FunctionKind kind();
inline void set_kind(FunctionKind kind);
// Indicates whether or not the code in the shared function support // Indicates whether or not the code in the shared function support
// deoptimization. // deoptimization.
inline bool has_deoptimization_support(); inline bool has_deoptimization_support();
@ -7315,17 +7321,20 @@ class SharedFunctionInfo: public HeapObject {
kIsFunction, kIsFunction,
kDontCache, kDontCache,
kDontFlush, kDontFlush,
kIsGenerator,
kIsArrow, kIsArrow,
kIsGenerator,
kIsConciseMethod,
kCompilerHintsCount // Pseudo entry kCompilerHintsCount // Pseudo entry
}; };
class DeoptCountBits: public BitField<int, 0, 4> {}; class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 3> {};
class OptReenableTriesBits: public BitField<int, 4, 18> {};
class ICAgeBits: public BitField<int, 22, 8> {};
class OptCountBits: public BitField<int, 0, 22> {}; class DeoptCountBits : public BitField<int, 0, 4> {};
class DisabledOptimizationReasonBits: public BitField<int, 22, 8> {}; class OptReenableTriesBits : public BitField<int, 4, 18> {};
class ICAgeBits : public BitField<int, 22, 8> {};
class OptCountBits : public BitField<int, 0, 22> {};
class DisabledOptimizationReasonBits : public BitField<int, 22, 8> {};
private: private:
#if V8_HOST_ARCH_32_BIT #if V8_HOST_ARCH_32_BIT

View File

@ -724,18 +724,13 @@ Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
FunctionLiteral* ParserTraits::ParseFunctionLiteral( FunctionLiteral* ParserTraits::ParseFunctionLiteral(
const AstRawString* name, const AstRawString* name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind,
bool name_is_strict_reserved, int function_token_position, FunctionLiteral::FunctionType type,
bool is_generator, FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
int function_token_position, return parser_->ParseFunctionLiteral(
FunctionLiteral::FunctionType type, name, function_name_location, name_is_strict_reserved, kind,
FunctionLiteral::ArityRestriction arity_restriction, function_token_position, type, arity_restriction, ok);
bool* ok) {
return parser_->ParseFunctionLiteral(name, function_name_location,
name_is_strict_reserved, is_generator,
function_token_position, type,
arity_restriction, ok);
} }
@ -767,6 +762,7 @@ Parser::Parser(CompilationInfo* info, ParseInfo* parse_info)
set_allow_arrow_functions(FLAG_harmony_arrow_functions); set_allow_arrow_functions(FLAG_harmony_arrow_functions);
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals); set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
set_allow_classes(FLAG_harmony_classes); set_allow_classes(FLAG_harmony_classes);
set_allow_harmony_object_literals(FLAG_harmony_object_literals);
for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
++feature) { ++feature) {
use_counts_[feature] = 0; use_counts_[feature] = 0;
@ -911,8 +907,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
function_state.handler_count(), 0, function_state.handler_count(), 0,
FunctionLiteral::kNoDuplicateParameters, FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval, FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
FunctionLiteral::kNotParenthesized, FunctionLiteral::kNormalFunction, FunctionLiteral::kNotParenthesized, FunctionKind::kNormalFunction, 0);
0);
result->set_ast_properties(factory()->visitor()->ast_properties()); result->set_ast_properties(factory()->visitor()->ast_properties());
result->set_dont_optimize_reason( result->set_dont_optimize_reason(
factory()->visitor()->dont_optimize_reason()); factory()->visitor()->dont_optimize_reason());
@ -999,18 +994,16 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
? FunctionLiteral::ANONYMOUS_EXPRESSION ? FunctionLiteral::ANONYMOUS_EXPRESSION
: FunctionLiteral::NAMED_EXPRESSION) : FunctionLiteral::NAMED_EXPRESSION)
: FunctionLiteral::DECLARATION; : FunctionLiteral::DECLARATION;
bool is_generator = shared_info->is_generator();
bool ok = true; bool ok = true;
if (shared_info->is_arrow()) { if (shared_info->is_arrow()) {
DCHECK(!is_generator);
Expression* expression = ParseExpression(false, &ok); Expression* expression = ParseExpression(false, &ok);
DCHECK(expression->IsFunctionLiteral()); DCHECK(expression->IsFunctionLiteral());
result = expression->AsFunctionLiteral(); result = expression->AsFunctionLiteral();
} else { } else {
result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(), result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
false, // Strict mode name already checked. false, // Strict mode name already checked.
is_generator, RelocInfo::kNoPosition, shared_info->kind(), RelocInfo::kNoPosition,
function_type, function_type,
FunctionLiteral::NORMAL_ARITY, &ok); FunctionLiteral::NORMAL_ARITY, &ok);
} }
@ -1894,14 +1887,12 @@ Statement* Parser::ParseFunctionDeclaration(
bool is_strict_reserved = false; bool is_strict_reserved = false;
const AstRawString* name = ParseIdentifierOrStrictReservedWord( const AstRawString* name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK); &is_strict_reserved, CHECK_OK);
FunctionLiteral* fun = ParseFunctionLiteral(name, FunctionLiteral* fun =
scanner()->location(), ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
is_strict_reserved, is_generator ? FunctionKind::kGeneratorFunction
is_generator, : FunctionKind::kNormalFunction,
pos, pos, FunctionLiteral::DECLARATION,
FunctionLiteral::DECLARATION, FunctionLiteral::NORMAL_ARITY, CHECK_OK);
FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
// Even if we're not at the top-level of the global or a function // Even if we're not at the top-level of the global or a function
// scope, we treat it as such and introduce the function with its // scope, we treat it as such and introduce the function with its
// initial value upon entering the corresponding scope. // initial value upon entering the corresponding scope.
@ -3365,14 +3356,10 @@ int ParserTraits::DeclareArrowParametersFromExpression(
FunctionLiteral* Parser::ParseFunctionLiteral( FunctionLiteral* Parser::ParseFunctionLiteral(
const AstRawString* function_name, const AstRawString* function_name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
bool name_is_strict_reserved,
bool is_generator,
int function_token_pos,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction, FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
bool* ok) {
// Function :: // Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}' // '(' FormalParameterList? ')' '{' FunctionBody '}'
// //
@ -3385,6 +3372,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
int pos = function_token_pos == RelocInfo::kNoPosition int pos = function_token_pos == RelocInfo::kNoPosition
? peek_position() : function_token_pos; ? peek_position() : function_token_pos;
bool is_generator = IsGeneratorFunction(kind);
// Anonymous functions were passed either the empty symbol or a null // Anonymous functions were passed either the empty symbol or a null
// handle as the function name. Remember if we were passed a non-empty // handle as the function name. Remember if we were passed a non-empty
// handle to decide whether to invoke function name inference. // handle to decide whether to invoke function name inference.
@ -3593,7 +3582,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
} }
// Validate strict mode. // Validate strict mode.
if (strict_mode() == STRICT) { // Concise methods use StrictFormalParameters.
if (strict_mode() == STRICT || IsConciseMethod(kind)) {
CheckStrictFunctionNameAndParameters(function_name, CheckStrictFunctionNameAndParameters(function_name,
name_is_strict_reserved, name_is_strict_reserved,
function_name_location, function_name_location,
@ -3601,6 +3591,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
dupe_error_loc, dupe_error_loc,
reserved_loc, reserved_loc,
CHECK_OK); CHECK_OK);
}
if (strict_mode() == STRICT) {
CheckOctalLiteral(scope->start_position(), CheckOctalLiteral(scope->start_position(),
scope->end_position(), scope->end_position(),
CHECK_OK); CHECK_OK);
@ -3613,9 +3605,6 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
} }
} }
FunctionLiteral::KindFlag kind = is_generator
? FunctionLiteral::kGeneratorFunction
: FunctionLiteral::kNormalFunction;
FunctionLiteral* function_literal = factory()->NewFunctionLiteral( FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
function_name, ast_value_factory_, scope, body, function_name, ast_value_factory_, scope, body,
materialized_literal_count, expected_property_count, handler_count, materialized_literal_count, expected_property_count, handler_count,
@ -3775,6 +3764,8 @@ PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
reusable_preparser_->set_allow_harmony_numeric_literals( reusable_preparser_->set_allow_harmony_numeric_literals(
allow_harmony_numeric_literals()); allow_harmony_numeric_literals());
reusable_preparser_->set_allow_classes(allow_classes()); reusable_preparser_->set_allow_classes(allow_classes());
reusable_preparser_->set_allow_harmony_object_literals(
allow_harmony_object_literals());
} }
PreParser::PreParseResult result = PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(strict_mode(), reusable_preparser_->PreParseLazyFunction(strict_mode(),

View File

@ -573,14 +573,10 @@ class ParserTraits {
// Temporary glue; these functions will move to ParserBase. // Temporary glue; these functions will move to ParserBase.
Expression* ParseV8Intrinsic(bool* ok); Expression* ParseV8Intrinsic(bool* ok);
FunctionLiteral* ParseFunctionLiteral( FunctionLiteral* ParseFunctionLiteral(
const AstRawString* name, const AstRawString* name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind,
bool name_is_strict_reserved, int function_token_position, FunctionLiteral::FunctionType type,
bool is_generator, FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
int function_token_position,
FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok);
V8_INLINE void SkipLazyFunctionBody(const AstRawString* name, V8_INLINE void SkipLazyFunctionBody(const AstRawString* name,
int* materialized_literal_count, int* materialized_literal_count,
int* expected_property_count, bool* ok); int* expected_property_count, bool* ok);
@ -746,14 +742,10 @@ class Parser : public ParserBase<ParserTraits> {
Statement* body, bool* ok); Statement* body, bool* ok);
FunctionLiteral* ParseFunctionLiteral( FunctionLiteral* ParseFunctionLiteral(
const AstRawString* name, const AstRawString* name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind,
bool name_is_strict_reserved, int function_token_position, FunctionLiteral::FunctionType type,
bool is_generator, FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
int function_token_position,
FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok);
// Magical syntax support. // Magical syntax support.
Expression* ParseV8Intrinsic(bool* ok); Expression* ParseV8Intrinsic(bool* ok);

View File

@ -102,16 +102,12 @@ PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
PreParserExpression PreParserTraits::ParseFunctionLiteral( PreParserExpression PreParserTraits::ParseFunctionLiteral(
PreParserIdentifier name, PreParserIdentifier name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind,
bool name_is_strict_reserved, int function_token_position, FunctionLiteral::FunctionType type,
bool is_generator, FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
int function_token_position,
FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok) {
return pre_parser_->ParseFunctionLiteral( return pre_parser_->ParseFunctionLiteral(
name, function_name_location, name_is_strict_reserved, is_generator, name, function_name_location, name_is_strict_reserved, kind,
function_token_position, type, arity_restriction, ok); function_token_position, type, arity_restriction, ok);
} }
@ -340,14 +336,11 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
bool is_strict_reserved = false; bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord( Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK); &is_strict_reserved, CHECK_OK);
ParseFunctionLiteral(name, ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
scanner()->location(), is_generator ? FunctionKind::kGeneratorFunction
is_strict_reserved, : FunctionKind::kNormalFunction,
is_generator, pos, FunctionLiteral::DECLARATION,
pos, FunctionLiteral::NORMAL_ARITY, CHECK_OK);
FunctionLiteral::DECLARATION,
FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
return Statement::FunctionDeclaration(); return Statement::FunctionDeclaration();
} }
@ -805,14 +798,10 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
PreParser::Expression PreParser::ParseFunctionLiteral( PreParser::Expression PreParser::ParseFunctionLiteral(
Identifier function_name, Identifier function_name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
bool name_is_strict_reserved,
bool is_generator,
int function_token_pos,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction, FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
bool* ok) {
// Function :: // Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}' // '(' FormalParameterList? ')' '{' FunctionBody '}'
@ -821,7 +810,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
PreParserScope function_scope(scope_, FUNCTION_SCOPE); PreParserScope function_scope(scope_, FUNCTION_SCOPE);
FunctionState function_state(&function_state_, &scope_, &function_scope, NULL, FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
this->ast_value_factory()); this->ast_value_factory());
function_state.set_is_generator(is_generator); function_state.set_is_generator(IsGeneratorFunction(kind));
// FormalParameterList :: // FormalParameterList ::
// '(' (Identifier)*[','] ')' // '(' (Identifier)*[','] ')'
Expect(Token::LPAREN, CHECK_OK); Expect(Token::LPAREN, CHECK_OK);
@ -876,7 +865,8 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
// Validate strict mode. We can do this only after parsing the function, // Validate strict mode. We can do this only after parsing the function,
// since the function can declare itself strict. // since the function can declare itself strict.
if (strict_mode() == STRICT) { // Concise methods use StrictFormalParameters.
if (strict_mode() == STRICT || IsConciseMethod(kind)) {
if (function_name.IsEvalOrArguments()) { if (function_name.IsEvalOrArguments()) {
ReportMessageAt(function_name_location, "strict_eval_arguments"); ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false; *ok = false;

View File

@ -85,6 +85,7 @@ class ParserBase : public Traits {
allow_natives_syntax_(false), allow_natives_syntax_(false),
allow_generators_(false), allow_generators_(false),
allow_arrow_functions_(false), allow_arrow_functions_(false),
allow_harmony_object_literals_(false),
zone_(zone), zone_(zone),
ast_node_id_gen_(ast_node_id_gen) {} ast_node_id_gen_(ast_node_id_gen) {}
@ -100,6 +101,9 @@ class ParserBase : public Traits {
return scanner()->HarmonyNumericLiterals(); return scanner()->HarmonyNumericLiterals();
} }
bool allow_classes() const { return scanner()->HarmonyClasses(); } bool allow_classes() const { return scanner()->HarmonyClasses(); }
bool allow_harmony_object_literals() const {
return allow_harmony_object_literals_;
}
// Setters that determine whether certain syntactical constructs are // Setters that determine whether certain syntactical constructs are
// allowed to be parsed by this instance of the parser. // allowed to be parsed by this instance of the parser.
@ -114,8 +118,9 @@ class ParserBase : public Traits {
void set_allow_harmony_numeric_literals(bool allow) { void set_allow_harmony_numeric_literals(bool allow) {
scanner()->SetHarmonyNumericLiterals(allow); scanner()->SetHarmonyNumericLiterals(allow);
} }
void set_allow_classes(bool allow) { void set_allow_classes(bool allow) { scanner()->SetHarmonyClasses(allow); }
scanner()->SetHarmonyClasses(allow); void set_allow_harmony_object_literals(bool allow) {
allow_harmony_object_literals_ = allow;
} }
protected: protected:
@ -481,6 +486,7 @@ class ParserBase : public Traits {
ExpressionT ParseObjectLiteral(bool* ok); ExpressionT ParseObjectLiteral(bool* ok);
ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker, ObjectLiteralPropertyT ParsePropertyDefinition(ObjectLiteralChecker* checker,
bool* ok); bool* ok);
IdentifierT ParsePropertyName(bool* is_getter, bool* is_setter, bool* ok);
typename Traits::Type::ExpressionList ParseArguments(bool* ok); typename Traits::Type::ExpressionList ParseArguments(bool* ok);
ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok); ExpressionT ParseAssignmentExpression(bool accept_IN, bool* ok);
ExpressionT ParseYieldExpression(bool* ok); ExpressionT ParseYieldExpression(bool* ok);
@ -579,6 +585,7 @@ class ParserBase : public Traits {
bool allow_natives_syntax_; bool allow_natives_syntax_;
bool allow_generators_; bool allow_generators_;
bool allow_arrow_functions_; bool allow_arrow_functions_;
bool allow_harmony_object_literals_;
typename Traits::Type::Zone* zone_; // Only used by Parser. typename Traits::Type::Zone* zone_; // Only used by Parser.
AstNode::IdGen* ast_node_id_gen_; AstNode::IdGen* ast_node_id_gen_;
@ -1054,8 +1061,8 @@ class PreParserFactory {
FunctionLiteral::ParameterFlag has_duplicate_parameters, FunctionLiteral::ParameterFlag has_duplicate_parameters,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
FunctionLiteral::IsFunctionFlag is_function, FunctionLiteral::IsFunctionFlag is_function,
FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionLiteral::IsParenthesizedFlag is_parenthesized, FunctionKind kind,
FunctionLiteral::KindFlag kind, int position) { int position) {
return PreParserExpression::Default(); return PreParserExpression::Default();
} }
@ -1331,14 +1338,10 @@ class PreParserTraits {
// Temporary glue; these functions will move to ParserBase. // Temporary glue; these functions will move to ParserBase.
PreParserExpression ParseV8Intrinsic(bool* ok); PreParserExpression ParseV8Intrinsic(bool* ok);
PreParserExpression ParseFunctionLiteral( PreParserExpression ParseFunctionLiteral(
PreParserIdentifier name, PreParserIdentifier name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind,
bool name_is_strict_reserved, int function_token_position, FunctionLiteral::FunctionType type,
bool is_generator, FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
int function_token_position,
FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok);
private: private:
PreParser* pre_parser_; PreParser* pre_parser_;
@ -1469,14 +1472,10 @@ class PreParser : public ParserBase<PreParserTraits> {
bool is_generator, bool* ok); bool is_generator, bool* ok);
Expression ParseFunctionLiteral( Expression ParseFunctionLiteral(
Identifier name, Identifier name, Scanner::Location function_name_location,
Scanner::Location function_name_location, bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
bool name_is_strict_reserved,
bool is_generator,
int function_token_pos,
FunctionLiteral::FunctionType function_type, FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction, FunctionLiteral::ArityRestriction arity_restriction, bool* ok);
bool* ok);
void ParseLazyFunctionLiteralBody(bool* ok); void ParseLazyFunctionLiteralBody(bool* ok);
bool CheckInOrOf(bool accept_OF); bool CheckInOrOf(bool accept_OF);
@ -1851,85 +1850,86 @@ typename ParserBase<Traits>::ExpressionT ParserBase<Traits>::ParseArrayLiteral(
} }
template <class Traits>
typename ParserBase<Traits>::IdentifierT ParserBase<Traits>::ParsePropertyName(
bool* is_getter, bool* is_setter, bool* ok) {
Token::Value next = peek();
switch (next) {
case Token::STRING:
Consume(Token::STRING);
return this->GetSymbol(scanner_);
case Token::NUMBER:
Consume(Token::NUMBER);
return this->GetNumberAsSymbol(scanner_);
default:
return ParseIdentifierNameOrGetOrSet(is_getter, is_setter,
CHECK_OK_CUSTOM(EmptyIdentifier));
}
}
template <class Traits> template <class Traits>
typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase< typename ParserBase<Traits>::ObjectLiteralPropertyT ParserBase<
Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) { Traits>::ParsePropertyDefinition(ObjectLiteralChecker* checker, bool* ok) {
LiteralT key = this->EmptyLiteral(); // TODO(arv): Add support for concise generator methods.
Token::Value next = peek(); ExpressionT value = this->EmptyExpression();
bool is_getter = false;
bool is_setter = false;
Token::Value name_token = peek();
int next_pos = peek_position(); int next_pos = peek_position();
IdentifierT name = ParsePropertyName(
&is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
if (fni_ != NULL) this->PushLiteralName(fni_, name);
switch (next) { if (peek() == Token::COLON) {
case Token::STRING: { // PropertyDefinition : PropertyName ':' AssignmentExpression
Consume(Token::STRING); checker->CheckProperty(name_token, kValueProperty,
IdentifierT string = this->GetSymbol(scanner_); CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
if (fni_ != NULL) this->PushLiteralName(fni_, string); Consume(Token::COLON);
uint32_t index; value = this->ParseAssignmentExpression(
if (this->IsArrayIndex(string, &index)) { true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
key = factory()->NewNumberLiteral(index, next_pos);
break;
}
key = factory()->NewStringLiteral(string, next_pos);
break;
}
case Token::NUMBER: {
Consume(Token::NUMBER);
key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
factory());
break;
}
default: {
bool is_getter = false;
bool is_setter = false;
IdentifierT id = ParseIdentifierNameOrGetOrSet(
&is_getter, &is_setter, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
if (fni_ != NULL) this->PushLiteralName(fni_, id);
if ((is_getter || is_setter) && peek() != Token::COLON) { } else if (allow_harmony_object_literals_ && peek() == Token::LPAREN) {
// Special handling of getter and setter syntax: // Concise Method
// { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... } checker->CheckProperty(name_token, kValueProperty,
// We have already read the "get" or "set" keyword. CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
IdentifierT name = this->EmptyIdentifier(); value = this->ParseFunctionLiteral(
switch (peek()) { name, scanner()->location(),
case Token::STRING: false, // reserved words are allowed here
Consume(Token::STRING); FunctionKind::kConciseMethod, RelocInfo::kNoPosition,
name = this->GetSymbol(scanner_); FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::NORMAL_ARITY,
break; CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
case Token::NUMBER:
Consume(Token::NUMBER); } else if (is_getter || is_setter) {
name = this->GetNumberAsSymbol(scanner_); // Accessor
break; bool dont_care = false;
default: name_token = peek();
name = ParseIdentifierName( name = ParsePropertyName(&dont_care, &dont_care,
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
} // Validate the property.
// Validate the property. checker->CheckProperty(name_token,
PropertyKind type = is_getter ? kGetterProperty : kSetterProperty; is_getter ? kGetterProperty : kSetterProperty,
checker->CheckProperty(next, type, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); typename Traits::Type::FunctionLiteral value = this->ParseFunctionLiteral(
typename Traits::Type::FunctionLiteral value = name, scanner()->location(),
this->ParseFunctionLiteral( false, // reserved words are allowed here
name, scanner()->location(), FunctionKind::kNormalFunction, RelocInfo::kNoPosition,
false, // reserved words are allowed here FunctionLiteral::ANONYMOUS_EXPRESSION,
false, // not a generator is_getter ? FunctionLiteral::GETTER_ARITY
RelocInfo::kNoPosition, FunctionLiteral::ANONYMOUS_EXPRESSION, : FunctionLiteral::SETTER_ARITY,
is_getter ? FunctionLiteral::GETTER_ARITY CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
: FunctionLiteral::SETTER_ARITY, return factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); } else {
return factory()->NewObjectLiteralProperty(is_getter, value, next_pos); Token::Value next = Next();
} ReportUnexpectedToken(next);
// Failed to parse as get/set property, so it's just a normal property *ok = false;
// (which might be called "get" or "set" or something else). return this->EmptyObjectLiteralProperty();
key = factory()->NewStringLiteral(id, next_pos);
}
} }
// Validate the property uint32_t index;
checker->CheckProperty(next, kValueProperty, LiteralT key = this->IsArrayIndex(name, &index)
CHECK_OK_CUSTOM(EmptyObjectLiteralProperty)); ? factory()->NewNumberLiteral(index, next_pos)
: factory()->NewStringLiteral(name, next_pos);
Expect(Token::COLON, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
ExpressionT value = this->ParseAssignmentExpression(
true, CHECK_OK_CUSTOM(EmptyObjectLiteralProperty));
return factory()->NewObjectLiteralProperty(key, value); return factory()->NewObjectLiteralProperty(key, value);
} }
@ -2428,14 +2428,12 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) {
function_name_location = scanner()->location(); function_name_location = scanner()->location();
function_type = FunctionLiteral::NAMED_EXPRESSION; function_type = FunctionLiteral::NAMED_EXPRESSION;
} }
result = this->ParseFunctionLiteral(name, result = this->ParseFunctionLiteral(
function_name_location, name, function_name_location, is_strict_reserved_name,
is_strict_reserved_name, is_generator ? FunctionKind::kGeneratorFunction
is_generator, : FunctionKind::kNormalFunction,
function_token_position, function_token_position, function_type, FunctionLiteral::NORMAL_ARITY,
function_type, CHECK_OK);
FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
} else if (peek() == Token::SUPER) { } else if (peek() == Token::SUPER) {
int beg_pos = position(); int beg_pos = position();
Consume(Token::SUPER); Consume(Token::SUPER);
@ -2596,7 +2594,7 @@ typename ParserBase<Traits>::ExpressionT ParserBase<
materialized_literal_count, expected_property_count, handler_count, materialized_literal_count, expected_property_count, handler_count,
num_parameters, FunctionLiteral::kNoDuplicateParameters, num_parameters, FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction, FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kIsFunction,
FunctionLiteral::kNotParenthesized, FunctionLiteral::kArrowFunction, FunctionLiteral::kNotParenthesized, FunctionKind::kArrowFunction,
start_pos); start_pos);
function_literal->set_function_token_position(start_pos); function_literal->set_function_token_position(start_pos);

View File

@ -2775,6 +2775,14 @@ RUNTIME_FUNCTION(Runtime_FunctionIsArrow) {
} }
RUNTIME_FUNCTION(Runtime_FunctionIsConciseMethod) {
SealHandleScope shs(isolate);
DCHECK(args.length() == 1);
CONVERT_ARG_CHECKED(JSFunction, f, 0);
return isolate->heap()->ToBoolean(f->shared()->is_concise_method());
}
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) { RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
SealHandleScope shs(isolate); SealHandleScope shs(isolate);
DCHECK(args.length() == 1); DCHECK(args.length() == 1);
@ -8125,8 +8133,8 @@ RUNTIME_FUNCTION(Runtime_NewClosureFromStubFailure) {
CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
Handle<Context> context(isolate->context()); Handle<Context> context(isolate->context());
PretenureFlag pretenure_flag = NOT_TENURED; PretenureFlag pretenure_flag = NOT_TENURED;
return *isolate->factory()->NewFunctionFromSharedFunctionInfo( return *isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context,
shared, context, pretenure_flag); pretenure_flag);
} }

View File

@ -197,6 +197,7 @@ namespace internal {
F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1) \ F(FunctionMarkNameShouldPrintAsAnonymous, 1, 1) \
F(FunctionIsGenerator, 1, 1) \ F(FunctionIsGenerator, 1, 1) \
F(FunctionIsArrow, 1, 1) \ F(FunctionIsArrow, 1, 1) \
F(FunctionIsConciseMethod, 1, 1) \
F(FunctionBindArguments, 4, 1) \ F(FunctionBindArguments, 4, 1) \
F(BoundFunctionGetBindings, 1, 1) \ F(BoundFunctionGetBindings, 1, 1) \
F(FunctionRemovePrototype, 1, 1) \ F(FunctionRemovePrototype, 1, 1) \

View File

@ -1757,7 +1757,12 @@ function FunctionSourceString(func) {
var name = %FunctionNameShouldPrintAsAnonymous(func) var name = %FunctionNameShouldPrintAsAnonymous(func)
? 'anonymous' ? 'anonymous'
: %FunctionGetName(func); : %FunctionGetName(func);
var head = %FunctionIsGenerator(func) ? 'function* ' : 'function ';
// TODO(arv): Handle concise generator methods.
var head = %FunctionIsConciseMethod(func)
? ''
: %FunctionIsGenerator(func) ? 'function* ' : 'function ';
return head + name + source; return head + name + source;
} }

View File

@ -1288,9 +1288,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ Move(rbx, info); __ Move(rbx, info);
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -5457,9 +5457,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ Move(rbx, instr->hydrogen()->shared_info()); __ Move(rbx, instr->hydrogen()->shared_info());
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -1251,9 +1251,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
!pretenure && !pretenure &&
scope()->is_function_scope() && scope()->is_function_scope() &&
info->num_literals() == 0) { info->num_literals() == 0) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
info->strict_mode(),
info->is_generator());
__ mov(ebx, Immediate(info)); __ mov(ebx, Immediate(info));
__ CallStub(&stub); __ CallStub(&stub);
} else { } else {

View File

@ -5295,9 +5295,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning. // space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure(); bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) { if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(), FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->strict_mode(), instr->hydrogen()->kind());
instr->hydrogen()->is_generator());
__ mov(ebx, Immediate(instr->hydrogen()->shared_info())); __ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} else { } else {

View File

@ -1217,7 +1217,8 @@ enum ParserFlag {
kAllowGenerators, kAllowGenerators,
kAllowHarmonyNumericLiterals, kAllowHarmonyNumericLiterals,
kAllowArrowFunctions, kAllowArrowFunctions,
kAllowClasses kAllowClasses,
kAllowHarmonyObjectLiterals
}; };
@ -1237,6 +1238,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
parser->set_allow_generators(flags.Contains(kAllowGenerators)); parser->set_allow_generators(flags.Contains(kAllowGenerators));
parser->set_allow_harmony_numeric_literals( parser->set_allow_harmony_numeric_literals(
flags.Contains(kAllowHarmonyNumericLiterals)); flags.Contains(kAllowHarmonyNumericLiterals));
parser->set_allow_harmony_object_literals(
flags.Contains(kAllowHarmonyObjectLiterals));
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions)); parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
parser->set_allow_classes(flags.Contains(kAllowClasses)); parser->set_allow_classes(flags.Contains(kAllowClasses));
} }
@ -1446,9 +1449,11 @@ TEST(ParserSync) {
CcTest::i_isolate()->stack_guard()->SetStackLimit( CcTest::i_isolate()->stack_guard()->SetStackLimit(
i::GetCurrentStackPosition() - 128 * 1024); i::GetCurrentStackPosition() - 128 * 1024);
static const ParserFlag flags1[] = {kAllowLazy, kAllowHarmonyScoping, static const ParserFlag flags1[] = {
kAllowModules, kAllowGenerators, kAllowLazy, kAllowHarmonyScoping,
kAllowArrowFunctions}; kAllowModules, kAllowGenerators,
kAllowArrowFunctions, kAllowHarmonyNumericLiterals,
kAllowHarmonyObjectLiterals};
for (int i = 0; context_data[i][0] != NULL; ++i) { for (int i = 0; context_data[i][0] != NULL; ++i) {
for (int j = 0; statement_data[j] != NULL; ++j) { for (int j = 0; statement_data[j] != NULL; ++j) {
for (int k = 0; termination_data[k] != NULL; ++k) { for (int k = 0; termination_data[k] != NULL; ++k) {
@ -1523,9 +1528,12 @@ void RunParserSyncTest(const char* context_data[][2],
i::GetCurrentStackPosition() - 128 * 1024); i::GetCurrentStackPosition() - 128 * 1024);
static const ParserFlag default_flags[] = { static const ParserFlag default_flags[] = {
kAllowLazy, kAllowHarmonyScoping, kAllowModules, kAllowArrowFunctions, kAllowClasses,
kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions, kAllowGenerators, kAllowHarmonyNumericLiterals,
kAllowClasses}; kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
kAllowLazy, kAllowModules,
kAllowNativesSyntax,
};
ParserFlag* generated_flags = NULL; ParserFlag* generated_flags = NULL;
if (flags == NULL) { if (flags == NULL) {
flags = default_flags; flags = default_flags;
@ -2520,23 +2528,36 @@ TEST(ErrorsObjectLiteralChecking) {
}; };
const char* statement_data[] = { const char* statement_data[] = {
",", "foo: 1, get foo() {}", "foo: 1, set foo(v) {}", ",",
"\"foo\": 1, get \"foo\"() {}", "\"foo\": 1, set \"foo\"(v) {}", "foo: 1, get foo() {}",
"1: 1, get 1() {}", "1: 1, set 1() {}", "foo: 1, set foo(v) {}",
"\"foo\": 1, get \"foo\"() {}",
"\"foo\": 1, set \"foo\"(v) {}",
"1: 1, get 1() {}",
"1: 1, set 1() {}",
"get foo() {}, get foo() {}",
"set foo(_) {}, set foo(_) {}",
// It's counter-intuitive, but these collide too (even in classic // It's counter-intuitive, but these collide too (even in classic
// mode). Note that we can have "foo" and foo as properties in classic // mode). Note that we can have "foo" and foo as properties in classic
// mode, // mode,
// but we cannot have "foo" and get foo, or foo and get "foo". // but we cannot have "foo" and get foo, or foo and get "foo".
"foo: 1, get \"foo\"() {}", "foo: 1, set \"foo\"(v) {}", "foo: 1, get \"foo\"() {}",
"\"foo\": 1, get foo() {}", "\"foo\": 1, set foo(v) {}", "foo: 1, set \"foo\"(v) {}",
"1: 1, get \"1\"() {}", "1: 1, set \"1\"() {}", "\"foo\": 1, get foo() {}",
"\"foo\": 1, set foo(v) {}",
"1: 1, get \"1\"() {}",
"1: 1, set \"1\"() {}",
"\"1\": 1, get 1() {}" "\"1\": 1, get 1() {}"
"\"1\": 1, set 1(v) {}" "\"1\": 1, set 1(v) {}"
// Wrong number of parameters // Wrong number of parameters
"get bar(x) {}", "get bar(x) {}",
"get bar(x, y) {}", "set bar() {}", "set bar(x, y) {}", "get bar(x, y) {}",
"set bar() {}",
"set bar(x, y) {}",
// Parsing FunctionLiteral for getter or setter fails // Parsing FunctionLiteral for getter or setter fails
"get foo( +", "get foo() \"error\"", NULL}; "get foo( +",
"get foo() \"error\"",
NULL};
RunParserSyncTest(context_data, statement_data, kError); RunParserSyncTest(context_data, statement_data, kError);
} }
@ -2573,6 +2594,8 @@ TEST(NoErrorsObjectLiteralChecking) {
"\"foo\": 1, set \"bar\"(v) {}", "\"foo\": 1, set \"bar\"(v) {}",
"1: 1, get 2() {}", "1: 1, get 2() {}",
"1: 1, set 2(v) {}", "1: 1, set 2(v) {}",
"get: 1, get foo() {}",
"set: 1, set foo(_) {}",
// Keywords, future reserved and strict future reserved are also allowed as // Keywords, future reserved and strict future reserved are also allowed as
// property names. // property names.
"if: 4", "if: 4",
@ -3392,3 +3415,144 @@ TEST(ErrorsSuper) {
RunParserSyncTest(context_data, statement_data, kError, NULL, 0, RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
always_flags, arraysize(always_flags)); always_flags, arraysize(always_flags));
} }
TEST(NoErrorsMethodDefinition) {
const char* context_data[][2] = {{"({", "});"},
{"'use strict'; ({", "});"},
{NULL, NULL}};
const char* object_literal_body_data[] = {
"m() {}",
"m(x) { return x; }",
"m(x, y) {}, n() {}",
"set(x, y) {}",
"get(x, y) {}",
NULL
};
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
RunParserSyncTest(context_data, object_literal_body_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(MethodDefinitionNames) {
const char* context_data[][2] = {{"({", "(x, y) {}});"},
{"'use strict'; ({", "(x, y) {}});"},
{NULL, NULL}};
const char* name_data[] = {
"m",
"'m'",
"\"m\"",
"\"m n\"",
"true",
"false",
"null",
"0",
"1.2",
"1e1",
"1E1",
"1e+1",
"1e-1",
// Keywords
"async",
"await",
"break",
"case",
"catch",
"class",
"const",
"continue",
"debugger",
"default",
"delete",
"do",
"else",
"enum",
"export",
"extends",
"finally",
"for",
"function",
"if",
"implements",
"import",
"in",
"instanceof",
"interface",
"let",
"new",
"package",
"private",
"protected",
"public",
"return",
"static",
"super",
"switch",
"this",
"throw",
"try",
"typeof",
"var",
"void",
"while",
"with",
"yield",
NULL
};
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
RunParserSyncTest(context_data, name_data, kSuccess, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(MethodDefinitionStrictFormalParamereters) {
const char* context_data[][2] = {{"({method(", "){}});"},
{"'use strict'; ({method(", "){}});"},
{NULL, NULL}};
const char* params_data[] = {
"x, x",
"x, y, x",
"eval",
"arguments",
"var",
"const",
NULL
};
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
RunParserSyncTest(context_data, params_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
}
TEST(MethodDefinitionDuplicateProperty) {
// Duplicate properties are allowed in ES6 but we haven't removed that check
// yet.
const char* context_data[][2] = {{"'use strict'; ({", "});"},
{NULL, NULL}};
const char* params_data[] = {
"x: 1, x() {}",
"x() {}, x: 1",
"x() {}, get x() {}",
"x() {}, set x(_) {}",
"x() {}, x() {}",
"x() {}, y() {}, x() {}",
"x() {}, \"x\"() {}",
"x() {}, 'x'() {}",
"0() {}, '0'() {}",
"1.0() {}, 1: 1",
NULL
};
static const ParserFlag always_flags[] = {kAllowHarmonyObjectLiterals};
RunParserSyncTest(context_data, params_data, kError, NULL, 0,
always_flags, arraysize(always_flags));
}

View File

@ -0,0 +1,123 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-object-literals --allow-natives-syntax
(function TestDescriptor() {
var object = {
method() {
return 42;
}
};
assertEquals(42, object.method());
})();
(function TestDescriptor() {
var object = {
method() {
return 42;
}
};
var desc = Object.getOwnPropertyDescriptor(object, 'method');
assertTrue(desc.enumerable);
assertTrue(desc.configurable);
assertTrue(desc.writable);
assertEquals('function', typeof desc.value);
assertEquals(42, desc.value());
})();
(function TestProto() {
var object = {
method() {
return 42;
}
};
assertEquals(Function.prototype, Object.getPrototypeOf(object.method));
})();
(function TestNotConstructable() {
var object = {
method() {
return 42;
}
};
assertThrows(function() {
new object.method;
});
})();
(function TestFunctionName() {
var object = {
method() {
return 42;
},
1() {},
2.0() {}
};
var f = object.method;
assertEquals('method', f.name);
var g = object[1];
assertEquals('1', g.name);
var h = object[2];
assertEquals('2', h.name);
})();
(function TestNoBinding() {
var method = 'local';
var calls = 0;
var object = {
method() {
calls++;
assertEquals('local', method);
}
};
object.method();
assertEquals(1, calls);
})();
(function TestNoPrototype() {
var object = {
method() {
return 42;
}
};
var f = object.method;
assertFalse(f.hasOwnProperty('prototype'));
assertEquals(undefined, f.prototype);
f.prototype = 42;
assertEquals(42, f.prototype);
})();
(function TestToString() {
var object = {
method() { 42; }
};
assertEquals('method() { 42; }', object.method.toString());
})();
(function TestOptimized() {
var object = {
method() { return 42; }
};
assertEquals(42, object.method());
assertEquals(42, object.method());
%OptimizeFunctionOnNextCall(object.method);
assertEquals(42, object.method());
assertFalse(object.method.hasOwnProperty('prototype'));
})();

View File

@ -0,0 +1,5 @@
// Copyright 2014 the V8 project authors. All rights reserved.
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony --harmony-proxies
var _f = function() {};
%FunctionIsConciseMethod(_f);