// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/v8.h"
-
#include "src/ast.h"
#include "src/ast-numbering.h"
#include "src/scopes.h"
namespace v8 {
namespace internal {
-
class AstNumberingVisitor final : public AstVisitor {
public:
explicit AstNumberingVisitor(Isolate* isolate, Zone* zone)
void IncrementNodeCount() { properties_.add_node_count(1); }
void DisableSelfOptimization() {
- properties_.flags()->Add(kDontSelfOptimize);
+ properties_.flags() |= AstProperties::kDontSelfOptimize;
}
void DisableOptimization(BailoutReason reason) {
dont_optimize_reason_ = reason;
}
void DisableCrankshaft(BailoutReason reason) {
if (FLAG_turbo_shipping) {
- return properties_.flags()->Add(kDontCrankshaft);
+ properties_.flags() |= AstProperties::kDontCrankshaft;
+ } else {
+ dont_optimize_reason_ = reason;
+ DisableSelfOptimization();
}
- dont_optimize_reason_ = reason;
- DisableSelfOptimization();
}
template <typename Node>
#include "src/assembler.h"
#include "src/ast-value-factory.h"
#include "src/bailout-reason.h"
+#include "src/base/flags.h"
#include "src/factory.h"
#include "src/isolate.h"
#include "src/jsregexp.h"
friend class AstNodeFactory;
-enum AstPropertiesFlag { kDontSelfOptimize, kDontCrankshaft };
-
-
class FeedbackVectorRequirements {
public:
FeedbackVectorRequirements(int slots, int ic_slots)
class AstProperties final BASE_EMBEDDED {
public:
- class Flags : public EnumSet<AstPropertiesFlag, int> {};
+ enum Flag {
+ kNoFlags = 0,
+ kDontSelfOptimize = 1 << 0,
+ kDontCrankshaft = 1 << 1
+ };
+
+ typedef base::Flags<Flag> Flags;
explicit AstProperties(Zone* zone) : node_count_(0), spec_(zone) {}
- Flags* flags() { return &flags_; }
+ Flags& flags() { return flags_; }
+ Flags flags() const { return flags_; }
int node_count() { return node_count_; }
void add_node_count(int count) { node_count_ += count; }
ZoneFeedbackVectorSpec spec_;
};
+DEFINE_OPERATORS_FOR_FLAGS(AstProperties::Flags)
+
class AstNode: public ZoneObject {
public:
FunctionKind kind() const { return FunctionKindBits::decode(bitfield_); }
int ast_node_count() { return ast_properties_.node_count(); }
- AstProperties::Flags* flags() { return ast_properties_.flags(); }
+ AstProperties::Flags flags() const { return ast_properties_.flags(); }
void set_ast_properties(AstProperties* ast_properties) {
ast_properties_ = *ast_properties;
}
// profiler, so they trigger their own optimization when they're called
// for the SharedFunctionInfo::kCallsUntilPrimitiveOptimization-th time.
bool CompilationInfo::ShouldSelfOptimize() {
- return FLAG_crankshaft && !function()->flags()->Contains(kDontSelfOptimize) &&
+ return FLAG_crankshaft &&
+ !(function()->flags() & AstProperties::kDontSelfOptimize) &&
!function()->dont_optimize() &&
function()->scope()->AllowsLazyCompilation() &&
(!has_shared_info() || !shared_info()->optimization_disabled());
FunctionLiteral* lit = parse_info->function();
shared_info->set_ast_node_count(lit->ast_node_count());
MaybeDisableOptimization(shared_info, lit->dont_optimize_reason());
- shared_info->set_dont_crankshaft(lit->flags()->Contains(kDontCrankshaft));
+ shared_info->set_dont_crankshaft(lit->flags() &
+ AstProperties::kDontCrankshaft);
}
return true;
}
uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
bool found_eval_scope = false;
- EnumSet<int, uint32_t> check_depths;
+ uint32_t check_depths = 0;
for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
if (s->num_heap_slots() <= 0) continue;
// TODO(mstarzinger): If we have reached an eval scope, we check all
if (depth > DynamicGlobalAccess::kMaxCheckDepth) {
return DynamicGlobalAccess::kFullCheckRequired;
}
- check_depths.Add(depth);
+ check_depths |= 1 << depth;
}
- return check_depths.ToIntegral();
+ return check_depths;
}
uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
- EnumSet<int, uint32_t> check_depths;
+ uint32_t check_depths = 0;
for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
if (s->num_heap_slots() <= 0) continue;
if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
if (depth > DynamicContextAccess::kMaxCheckDepth) {
return DynamicContextAccess::kFullCheckRequired;
}
- check_depths.Add(depth);
+ check_depths |= 1 << depth;
if (s == variable->scope()) break;
}
- return check_depths.ToIntegral();
+ return check_depths;
}
if (lit->dont_optimize_reason() != kNoReason) {
shared_info->DisableOptimization(lit->dont_optimize_reason());
}
- shared_info->set_dont_crankshaft(
- lit->flags()->Contains(AstPropertiesFlag::kDontCrankshaft));
+ shared_info->set_dont_crankshaft(lit->flags() &
+ AstProperties::kDontCrankshaft);
shared_info->set_kind(lit->kind());
shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
shared_info->set_asm_function(lit->scope()->asm_function());
}
}
- SmiOperationExecutionMode mode;
- mode.Add(PRESERVE_SOURCE_REGISTER);
- mode.Add(BAILOUT_ON_NO_OVERFLOW);
+ SmiOperationConstraints constraints =
+ SmiOperationConstraint::kPreserveSourceRegister |
+ SmiOperationConstraint::kBailoutOnNoOverflow;
if (expr->op() == Token::INC) {
- __ SmiAddConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
+ __ SmiAddConstant(rax, rax, Smi::FromInt(1), constraints, &done,
+ Label::kNear);
} else {
- __ SmiSubConstant(rax, rax, Smi::FromInt(1), mode, &done, Label::kNear);
+ __ SmiSubConstant(rax, rax, Smi::FromInt(1), constraints, &done,
+ Label::kNear);
}
__ jmp(&stub_call, Label::kNear);
__ bind(&slow);
}
-void MacroAssembler::SmiAddConstant(Register dst,
- Register src,
- Smi* constant,
- SmiOperationExecutionMode mode,
+void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant,
+ SmiOperationConstraints constraints,
Label* bailout_label,
Label::Distance near_jump) {
if (constant->value() == 0) {
DCHECK(!dst.is(kScratchRegister));
LoadSmiConstant(kScratchRegister, constant);
addp(dst, kScratchRegister);
- if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
+ if (constraints & SmiOperationConstraint::kBailoutOnNoOverflow) {
j(no_overflow, bailout_label, near_jump);
- DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
+ DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
subp(dst, kScratchRegister);
- } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
- if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
+ } else if (constraints & SmiOperationConstraint::kBailoutOnOverflow) {
+ if (constraints & SmiOperationConstraint::kPreserveSourceRegister) {
Label done;
j(no_overflow, &done, Label::kNear);
subp(dst, kScratchRegister);
j(overflow, bailout_label, near_jump);
}
} else {
- CHECK(mode.IsEmpty());
+ UNREACHABLE();
}
} else {
- DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
- DCHECK(mode.Contains(BAILOUT_ON_OVERFLOW));
+ DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
+ DCHECK(constraints & SmiOperationConstraint::kBailoutOnOverflow);
LoadSmiConstant(dst, constant);
addp(dst, src);
j(overflow, bailout_label, near_jump);
}
-void MacroAssembler::SmiSubConstant(Register dst,
- Register src,
- Smi* constant,
- SmiOperationExecutionMode mode,
+void MacroAssembler::SmiSubConstant(Register dst, Register src, Smi* constant,
+ SmiOperationConstraints constraints,
Label* bailout_label,
Label::Distance near_jump) {
if (constant->value() == 0) {
DCHECK(!dst.is(kScratchRegister));
LoadSmiConstant(kScratchRegister, constant);
subp(dst, kScratchRegister);
- if (mode.Contains(BAILOUT_ON_NO_OVERFLOW)) {
+ if (constraints & SmiOperationConstraint::kBailoutOnNoOverflow) {
j(no_overflow, bailout_label, near_jump);
- DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
+ DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
addp(dst, kScratchRegister);
- } else if (mode.Contains(BAILOUT_ON_OVERFLOW)) {
- if (mode.Contains(PRESERVE_SOURCE_REGISTER)) {
+ } else if (constraints & SmiOperationConstraint::kBailoutOnOverflow) {
+ if (constraints & SmiOperationConstraint::kPreserveSourceRegister) {
Label done;
j(no_overflow, &done, Label::kNear);
addp(dst, kScratchRegister);
j(overflow, bailout_label, near_jump);
}
} else {
- CHECK(mode.IsEmpty());
+ UNREACHABLE();
}
} else {
- DCHECK(mode.Contains(PRESERVE_SOURCE_REGISTER));
- DCHECK(mode.Contains(BAILOUT_ON_OVERFLOW));
+ DCHECK(constraints & SmiOperationConstraint::kPreserveSourceRegister);
+ DCHECK(constraints & SmiOperationConstraint::kBailoutOnOverflow);
if (constant->value() == Smi::kMinValue) {
DCHECK(!dst.is(kScratchRegister));
movp(dst, src);
#include "src/assembler.h"
#include "src/bailout-reason.h"
+#include "src/base/flags.h"
#include "src/frames.h"
#include "src/globals.h"
kPointersToHereAreAlwaysInteresting
};
-enum SmiOperationConstraint {
- PRESERVE_SOURCE_REGISTER,
- BAILOUT_ON_NO_OVERFLOW,
- BAILOUT_ON_OVERFLOW,
- NUMBER_OF_CONSTRAINTS
+enum class SmiOperationConstraint {
+ kPreserveSourceRegister = 1 << 0,
+ kBailoutOnNoOverflow = 1 << 1,
+ kBailoutOnOverflow = 1 << 2
};
-STATIC_ASSERT(NUMBER_OF_CONSTRAINTS <= 8);
+typedef base::Flags<SmiOperationConstraint> SmiOperationConstraints;
-class SmiOperationExecutionMode : public EnumSet<SmiOperationConstraint, byte> {
- public:
- SmiOperationExecutionMode() : EnumSet<SmiOperationConstraint, byte>(0) { }
- explicit SmiOperationExecutionMode(byte bits)
- : EnumSet<SmiOperationConstraint, byte>(bits) { }
-};
+DEFINE_OPERATORS_FOR_FLAGS(SmiOperationConstraints)
#ifdef DEBUG
bool AreAliased(Register reg1,
// Add an integer constant to a tagged smi, giving a tagged smi as result,
// or jumping to a label if the result cannot be represented by a smi.
- void SmiAddConstant(Register dst,
- Register src,
- Smi* constant,
- SmiOperationExecutionMode mode,
- Label* bailout_label,
+ void SmiAddConstant(Register dst, Register src, Smi* constant,
+ SmiOperationConstraints constraints, Label* bailout_label,
Label::Distance near_jump = Label::kFar);
// Subtract an integer constant from a tagged smi, giving a tagged smi as
// Subtract an integer constant from a tagged smi, giving a tagged smi as
// result, or jumping to a label if the result cannot be represented by a smi.
- void SmiSubConstant(Register dst,
- Register src,
- Smi* constant,
- SmiOperationExecutionMode mode,
- Label* bailout_label,
+ void SmiSubConstant(Register dst, Register src, Smi* constant,
+ SmiOperationConstraints constraints, Label* bailout_label,
Label::Distance near_jump = Label::kFar);
// Negating a smi can give a negative zero or too large positive value.
__ movl(rcx, Immediate(first));
__ Integer32ToSmi(rcx, rcx);
- i::SmiOperationExecutionMode mode;
- mode.Add(i::PRESERVE_SOURCE_REGISTER);
- mode.Add(i::BAILOUT_ON_OVERFLOW);
+ i::SmiOperationConstraints constraints =
+ i::SmiOperationConstraint::kPreserveSourceRegister |
+ i::SmiOperationConstraint::kBailoutOnOverflow;
__ incq(rax);
- __ SmiAddConstant(r9, rcx, Smi::FromInt(second), mode, exit);
+ __ SmiAddConstant(r9, rcx, Smi::FromInt(second), constraints, exit);
__ cmpq(r9, r8);
__ j(not_equal, exit);
__ incq(rax);
- __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
+ __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), constraints, exit);
__ cmpq(rcx, r8);
__ j(not_equal, exit);
__ movl(rcx, Immediate(first));
__ Integer32ToSmi(rcx, rcx);
- mode.RemoveAll();
- mode.Add(i::PRESERVE_SOURCE_REGISTER);
- mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
+ constraints = i::SmiOperationConstraint::kPreserveSourceRegister |
+ i::SmiOperationConstraint::kBailoutOnNoOverflow;
Label done;
__ incq(rax);
- __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
+ __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), constraints, &done);
__ jmp(exit);
__ bind(&done);
__ cmpq(rcx, r8);
__ j(not_equal, exit);
}
- i::SmiOperationExecutionMode mode;
- mode.Add(i::PRESERVE_SOURCE_REGISTER);
- mode.Add(i::BAILOUT_ON_OVERFLOW);
+ i::SmiOperationConstraints constraints =
+ i::SmiOperationConstraint::kPreserveSourceRegister |
+ i::SmiOperationConstraint::kBailoutOnOverflow;
__ movq(rcx, r11);
{
Label overflow_ok;
__ incq(rax);
- __ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
+ __ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
{
Label overflow_ok;
__ incq(rax);
- __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
+ __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
{
Label overflow_ok;
__ incq(rax);
- __ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
+ __ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ j(not_equal, exit);
}
- mode.RemoveAll();
- mode.Add(i::BAILOUT_ON_OVERFLOW);
+ constraints = i::SmiOperationConstraint::kBailoutOnOverflow;
{
Label overflow_ok;
__ incq(rax);
- __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
+ __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ cmpq(rcx, r8);
__ j(not_equal, exit);
- i::SmiOperationExecutionMode mode;
- mode.Add(i::PRESERVE_SOURCE_REGISTER);
- mode.Add(i::BAILOUT_ON_OVERFLOW);
+ i::SmiOperationConstraints constraints =
+ i::SmiOperationConstraint::kPreserveSourceRegister |
+ i::SmiOperationConstraint::kBailoutOnOverflow;
__ Move(rcx, Smi::FromInt(first));
__ incq(rax); // Test 4.
- __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, exit);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), constraints, exit);
__ cmpq(rcx, r8);
__ j(not_equal, exit);
__ Move(rcx, Smi::FromInt(first));
__ incq(rax); // Test 5.
- __ SmiSubConstant(r9, rcx, Smi::FromInt(second), mode, exit);
+ __ SmiSubConstant(r9, rcx, Smi::FromInt(second), constraints, exit);
__ cmpq(r9, r8);
__ j(not_equal, exit);
- mode.RemoveAll();
- mode.Add(i::PRESERVE_SOURCE_REGISTER);
- mode.Add(i::BAILOUT_ON_NO_OVERFLOW);
+ constraints = i::SmiOperationConstraint::kPreserveSourceRegister |
+ i::SmiOperationConstraint::kBailoutOnNoOverflow;
__ Move(rcx, Smi::FromInt(first));
Label done;
__ incq(rax); // Test 6.
- __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), mode, &done);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), constraints, &done);
__ jmp(exit);
__ bind(&done);
__ cmpq(rcx, r8);
__ j(not_equal, exit);
}
- i::SmiOperationExecutionMode mode;
- mode.Add(i::PRESERVE_SOURCE_REGISTER);
- mode.Add(i::BAILOUT_ON_OVERFLOW);
+ i::SmiOperationConstraints constraints =
+ i::SmiOperationConstraint::kPreserveSourceRegister |
+ i::SmiOperationConstraint::kBailoutOnOverflow;
__ movq(rcx, r11);
{
Label overflow_ok;
__ incq(rax);
- __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
+ __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
{
Label overflow_ok;
__ incq(rax);
- __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), mode, &overflow_ok);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
{
Label overflow_ok;
__ incq(rax);
- __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);
__ j(not_equal, exit);
}
- mode.RemoveAll();
- mode.Add(i::BAILOUT_ON_OVERFLOW);
+ constraints = i::SmiOperationConstraint::kBailoutOnOverflow;
__ movq(rcx, r11);
{
Label overflow_ok;
__ incq(rax);
- __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), mode, &overflow_ok);
+ __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
__ jmp(exit);
__ bind(&overflow_ok);
__ incq(rax);