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 &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
FastNewClosureStub stub(isolate(),
info->strict_mode(),
info->is_generator());
FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ mov(r2, Operand(info));
__ CallStub(&stub);
} else {

View File

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

View File

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

View File

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

View File

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

View File

@ -1343,7 +1343,7 @@ HValue* CodeStubGraphBuilder<FastNewClosureStub>::BuildCodeStub() {
NOT_TENURED, JS_FUNCTION_TYPE);
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
// as the map of the allocated object.

View File

@ -551,21 +551,27 @@ class NumberToStringStub FINAL : public HydrogenCodeStub {
class FastNewClosureStub : public HydrogenCodeStub {
public:
FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
bool is_generator)
FunctionKind kind)
: HydrogenCodeStub(isolate) {
DCHECK(IsValidFunctionKind(kind));
set_sub_minor_key(StrictModeBits::encode(strict_mode) |
IsGeneratorBits::encode(is_generator));
FunctionKindBits::encode(kind));
}
StrictMode strict_mode() const {
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:
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_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_bailout_reason(lit->dont_optimize_reason());
function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
function_info->set_is_generator(lit->is_generator());
function_info->set_is_arrow(lit->is_arrow());
function_info->set_kind(lit->kind());
}
@ -871,9 +870,8 @@ static Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
// Allocate function.
DCHECK(!info->code().is_null());
result = isolate->factory()->NewSharedFunctionInfo(
lit->name(), lit->materialized_literal_count(), lit->is_generator(),
lit->is_arrow(), info->code(),
ScopeInfo::Create(info->scope(), info->zone()),
lit->name(), lit->materialized_literal_count(), lit->kind(),
info->code(), ScopeInfo::Create(info->scope(), info->zone()),
info->feedback_vector());
DCHECK_EQ(RelocInfo::kNoPosition, lit->function_token_position());
@ -1094,9 +1092,8 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(
// Create a shared function info object.
Handle<SharedFunctionInfo> result = factory->NewSharedFunctionInfo(
literal->name(), literal->materialized_literal_count(),
literal->is_generator(), literal->is_arrow(), info.code(), scope_info,
info.feedback_vector());
literal->name(), literal->materialized_literal_count(), literal->kind(),
info.code(), scope_info, info.feedback_vector());
SetFunctionInfo(result, literal, false, script);
RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
result->set_allows_lazy_compilation(allow_lazy);

View File

@ -553,14 +553,20 @@ class Context: public FixedArray {
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
}
static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) {
return is_generator
? (strict_mode == SLOPPY
? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
: STRICT_GENERATOR_FUNCTION_MAP_INDEX)
: (strict_mode == SLOPPY
? SLOPPY_FUNCTION_MAP_INDEX
: STRICT_FUNCTION_MAP_INDEX);
static int FunctionMapIndex(StrictMode strict_mode, FunctionKind kind) {
if (IsGeneratorFunction(kind)) {
return strict_mode == SLOPPY ? SLOPPY_GENERATOR_FUNCTION_MAP_INDEX
: STRICT_GENERATOR_FUNCTION_MAP_INDEX;
}
if (IsConciseMethod(kind)) {
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;

View File

@ -1237,6 +1237,9 @@ void Factory::InitializeFunction(Handle<JSFunction> function,
function->set_prototype_or_initial_map(*the_hole_value());
function->set_literals_or_bindings(*empty_fixed_array());
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();
}
@ -1356,8 +1359,7 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
Handle<SharedFunctionInfo> info,
Handle<Context> context,
PretenureFlag pretenure) {
int map_index = Context::FunctionMapIndex(info->strict_mode(),
info->is_generator());
int map_index = Context::FunctionMapIndex(info->strict_mode(), info->kind());
Handle<Map> map(Map::cast(context->native_context()->get(map_index)));
Handle<JSFunction> result = NewFunction(map, info, context, pretenure);
@ -1904,13 +1906,14 @@ Handle<FixedArray> Factory::NewTypeFeedbackVector(int slot_count) {
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name, int number_of_literals, bool is_generator,
bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<String> name, int number_of_literals, FunctionKind kind,
Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector) {
DCHECK(IsValidFunctionKind(kind));
Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name, code);
shared->set_scope_info(*scope_info);
shared->set_feedback_vector(*feedback_vector);
shared->set_is_arrow(is_arrow);
shared->set_kind(kind);
int literals_array_size = number_of_literals;
// If the function contains object, regexp or array literals,
// allocate extra space for a literals array prefix containing the
@ -1919,7 +1922,7 @@ Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
literals_array_size += JSFunction::kLiteralsPrefixSize;
}
shared->set_num_literals(literals_array_size);
if (is_generator) {
if (IsGeneratorFunction(kind)) {
shared->set_instance_class_name(isolate()->heap()->Generator_string());
shared->DisableOptimization(kGenerator);
}

View File

@ -598,8 +598,8 @@ class Factory FINAL {
// Allocates a new SharedFunctionInfo object.
Handle<SharedFunctionInfo> NewSharedFunctionInfo(
Handle<String> name, int number_of_literals, bool is_generator,
bool is_arrow, Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<String> name, int number_of_literals, FunctionKind kind,
Handle<Code> code, Handle<ScopeInfo> scope_info,
Handle<FixedArray> feedback_vector);
Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name,
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_arrow_functions, false, "enable harmony arrow functions")
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_IMPLICATION(harmony, harmony_scoping)
@ -172,6 +174,7 @@ DEFINE_IMPLICATION(harmony, harmony_strings)
DEFINE_IMPLICATION(harmony, harmony_arrays)
DEFINE_IMPLICATION(harmony, harmony_arrow_functions)
DEFINE_IMPLICATION(harmony, harmony_classes)
DEFINE_IMPLICATION(harmony, harmony_object_literals)
DEFINE_IMPLICATION(harmony_modules, harmony_scoping)
DEFINE_IMPLICATION(harmony, es_staging)

View File

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

View File

@ -756,6 +756,41 @@ enum MinusZeroMode {
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 i = v8::internal;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5519,9 +5519,8 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
FastNewClosureStub stub(isolate(),
instr->hydrogen()->strict_mode(),
instr->hydrogen()->is_generator());
FastNewClosureStub stub(isolate(), instr->hydrogen()->strict_mode(),
instr->hydrogen()->kind());
__ li(a2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
} 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, inline_builtin,
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, dont_cache, kDontCache)
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_generator, kIsGenerator)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, is_concise_method,
kIsConciseMethod)
ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset)
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.
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
// deoptimization.
inline bool has_deoptimization_support();
@ -7315,17 +7321,20 @@ class SharedFunctionInfo: public HeapObject {
kIsFunction,
kDontCache,
kDontFlush,
kIsGenerator,
kIsArrow,
kIsGenerator,
kIsConciseMethod,
kCompilerHintsCount // Pseudo entry
};
class DeoptCountBits: public BitField<int, 0, 4> {};
class OptReenableTriesBits: public BitField<int, 4, 18> {};
class ICAgeBits: public BitField<int, 22, 8> {};
class FunctionKindBits : public BitField<FunctionKind, kIsArrow, 3> {};
class OptCountBits: public BitField<int, 0, 22> {};
class DisabledOptimizationReasonBits: public BitField<int, 22, 8> {};
class DeoptCountBits : public BitField<int, 0, 4> {};
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:
#if V8_HOST_ARCH_32_BIT

View File

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

View File

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

View File

@ -102,16 +102,12 @@ PreParserExpression PreParserTraits::ParseV8Intrinsic(bool* ok) {
PreParserExpression PreParserTraits::ParseFunctionLiteral(
PreParserIdentifier name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_position,
FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok) {
PreParserIdentifier name, Scanner::Location function_name_location,
bool name_is_strict_reserved, FunctionKind kind,
int function_token_position, FunctionLiteral::FunctionType type,
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
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);
}
@ -340,14 +336,11 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
bool is_strict_reserved = false;
Identifier name = ParseIdentifierOrStrictReservedWord(
&is_strict_reserved, CHECK_OK);
ParseFunctionLiteral(name,
scanner()->location(),
is_strict_reserved,
is_generator,
pos,
FunctionLiteral::DECLARATION,
FunctionLiteral::NORMAL_ARITY,
CHECK_OK);
ParseFunctionLiteral(name, scanner()->location(), is_strict_reserved,
is_generator ? FunctionKind::kGeneratorFunction
: FunctionKind::kNormalFunction,
pos, FunctionLiteral::DECLARATION,
FunctionLiteral::NORMAL_ARITY, CHECK_OK);
return Statement::FunctionDeclaration();
}
@ -805,14 +798,10 @@ PreParser::Statement PreParser::ParseDebuggerStatement(bool* ok) {
PreParser::Expression PreParser::ParseFunctionLiteral(
Identifier function_name,
Scanner::Location function_name_location,
bool name_is_strict_reserved,
bool is_generator,
int function_token_pos,
Identifier function_name, Scanner::Location function_name_location,
bool name_is_strict_reserved, FunctionKind kind, int function_token_pos,
FunctionLiteral::FunctionType function_type,
FunctionLiteral::ArityRestriction arity_restriction,
bool* ok) {
FunctionLiteral::ArityRestriction arity_restriction, bool* ok) {
// Function ::
// '(' FormalParameterList? ')' '{' FunctionBody '}'
@ -821,7 +810,7 @@ PreParser::Expression PreParser::ParseFunctionLiteral(
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
FunctionState function_state(&function_state_, &scope_, &function_scope, NULL,
this->ast_value_factory());
function_state.set_is_generator(is_generator);
function_state.set_is_generator(IsGeneratorFunction(kind));
// FormalParameterList ::
// '(' (Identifier)*[','] ')'
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,
// 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()) {
ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;

View File

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

View File

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

View File

@ -1757,7 +1757,12 @@ function FunctionSourceString(func) {
var name = %FunctionNameShouldPrintAsAnonymous(func)
? 'anonymous'
: %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;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1217,7 +1217,8 @@ enum ParserFlag {
kAllowGenerators,
kAllowHarmonyNumericLiterals,
kAllowArrowFunctions,
kAllowClasses
kAllowClasses,
kAllowHarmonyObjectLiterals
};
@ -1237,6 +1238,8 @@ void SetParserFlags(i::ParserBase<Traits>* parser,
parser->set_allow_generators(flags.Contains(kAllowGenerators));
parser->set_allow_harmony_numeric_literals(
flags.Contains(kAllowHarmonyNumericLiterals));
parser->set_allow_harmony_object_literals(
flags.Contains(kAllowHarmonyObjectLiterals));
parser->set_allow_arrow_functions(flags.Contains(kAllowArrowFunctions));
parser->set_allow_classes(flags.Contains(kAllowClasses));
}
@ -1446,9 +1449,11 @@ TEST(ParserSync) {
CcTest::i_isolate()->stack_guard()->SetStackLimit(
i::GetCurrentStackPosition() - 128 * 1024);
static const ParserFlag flags1[] = {kAllowLazy, kAllowHarmonyScoping,
kAllowModules, kAllowGenerators,
kAllowArrowFunctions};
static const ParserFlag flags1[] = {
kAllowLazy, kAllowHarmonyScoping,
kAllowModules, kAllowGenerators,
kAllowArrowFunctions, kAllowHarmonyNumericLiterals,
kAllowHarmonyObjectLiterals};
for (int i = 0; context_data[i][0] != NULL; ++i) {
for (int j = 0; statement_data[j] != NULL; ++j) {
for (int k = 0; termination_data[k] != NULL; ++k) {
@ -1523,9 +1528,12 @@ void RunParserSyncTest(const char* context_data[][2],
i::GetCurrentStackPosition() - 128 * 1024);
static const ParserFlag default_flags[] = {
kAllowLazy, kAllowHarmonyScoping, kAllowModules,
kAllowGenerators, kAllowNativesSyntax, kAllowArrowFunctions,
kAllowClasses};
kAllowArrowFunctions, kAllowClasses,
kAllowGenerators, kAllowHarmonyNumericLiterals,
kAllowHarmonyObjectLiterals, kAllowHarmonyScoping,
kAllowLazy, kAllowModules,
kAllowNativesSyntax,
};
ParserFlag* generated_flags = NULL;
if (flags == NULL) {
flags = default_flags;
@ -2520,23 +2528,36 @@ TEST(ErrorsObjectLiteralChecking) {
};
const char* statement_data[] = {
",", "foo: 1, get foo() {}", "foo: 1, set foo(v) {}",
"\"foo\": 1, get \"foo\"() {}", "\"foo\": 1, set \"foo\"(v) {}",
"1: 1, get 1() {}", "1: 1, set 1() {}",
",",
"foo: 1, get foo() {}",
"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
// mode). Note that we can have "foo" and foo as properties in classic
// mode,
// 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, set foo(v) {}",
"1: 1, get \"1\"() {}", "1: 1, set \"1\"() {}",
"foo: 1, get \"foo\"() {}",
"foo: 1, set \"foo\"(v) {}",
"\"foo\": 1, get foo() {}",
"\"foo\": 1, set foo(v) {}",
"1: 1, get \"1\"() {}",
"1: 1, set \"1\"() {}",
"\"1\": 1, get 1() {}"
"\"1\": 1, set 1(v) {}"
// Wrong number of parameters
"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
"get foo( +", "get foo() \"error\"", NULL};
"get foo( +",
"get foo() \"error\"",
NULL};
RunParserSyncTest(context_data, statement_data, kError);
}
@ -2573,6 +2594,8 @@ TEST(NoErrorsObjectLiteralChecking) {
"\"foo\": 1, set \"bar\"(v) {}",
"1: 1, get 2() {}",
"1: 1, set 2(v) {}",
"get: 1, get foo() {}",
"set: 1, set foo(_) {}",
// Keywords, future reserved and strict future reserved are also allowed as
// property names.
"if: 4",
@ -3392,3 +3415,144 @@ TEST(ErrorsSuper) {
RunParserSyncTest(context_data, statement_data, kError, NULL, 0,
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);