Version 3.25.8 (based on bleeding_edge revision r19840)
Fix HIsSmiAndBranch::KnownSuccessorBlock() by deleting it (Chromium issue 351320).
Fix handling of polymorphic array accesses with constant index (Chromium issue 351319).
Fix lazy deopt after tagged binary ops (Chromium issue 350434).
MIPS: Cleanup some of the range uses in ModI/DivI (issue 3204).
Fix issue with getOwnPropertySymbols and hidden properties (Chromium issue 350864).
Cleanup some of the range uses in ModI/DivI (issue 3204).
PromiseCoerce should ignore primitive values (Chromium issue 347095).
Use a per-isolate cache for the date object JS bits (Chromium issue 348856).
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@19841 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/a64/assembler-a64.h b/src/a64/assembler-a64.h
index cb018a4..999b01a 100644
--- a/src/a64/assembler-a64.h
+++ b/src/a64/assembler-a64.h
@@ -264,36 +264,60 @@
static const int kMaxNumRegisters = kNumberOfFPRegisters;
// Crankshaft can use all the FP registers except:
- // - d29 which is used in crankshaft as a double scratch register
- // - d30 which is used to keep the 0 double value
+ // - d15 which is used to keep the 0 double value
+ // - d30 which is used in crankshaft as a double scratch register
// - d31 which is used in the MacroAssembler as a double scratch register
- static const int kNumReservedRegisters = 3;
- static const int kMaxNumAllocatableRegisters =
- kNumberOfFPRegisters - kNumReservedRegisters;
- static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
- static const RegList kAllocatableFPRegisters =
- (1 << kMaxNumAllocatableRegisters) - 1;
+ static const unsigned kAllocatableLowRangeBegin = 0;
+ static const unsigned kAllocatableLowRangeEnd = 14;
+ static const unsigned kAllocatableHighRangeBegin = 16;
+ static const unsigned kAllocatableHighRangeEnd = 29;
- static FPRegister FromAllocationIndex(int index) {
- ASSERT((index >= 0) && (index < NumAllocatableRegisters()));
- return from_code(index);
+ static const RegList kAllocatableFPRegisters = 0x3fff7fff;
+
+ // Gap between low and high ranges.
+ static const int kAllocatableRangeGapSize =
+ (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
+
+ static const int kMaxNumAllocatableRegisters =
+ (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
+ (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1);
+ static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
+
+ // Return true if the register is one that crankshaft can allocate.
+ bool IsAllocatable() const {
+ return (Bit() & kAllocatableFPRegisters) != 0;
+ }
+
+ static FPRegister FromAllocationIndex(unsigned int index) {
+ ASSERT(index < static_cast<unsigned>(NumAllocatableRegisters()));
+
+ return (index <= kAllocatableLowRangeEnd)
+ ? from_code(index)
+ : from_code(index + kAllocatableRangeGapSize);
}
static const char* AllocationIndexToString(int index) {
ASSERT((index >= 0) && (index < NumAllocatableRegisters()));
+ ASSERT((kAllocatableLowRangeBegin == 0) &&
+ (kAllocatableLowRangeEnd == 14) &&
+ (kAllocatableHighRangeBegin == 16) &&
+ (kAllocatableHighRangeEnd == 29));
const char* const names[] = {
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
- "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
+ "d8", "d9", "d10", "d11", "d12", "d13", "d14",
"d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
- "d24", "d25", "d26", "d27", "d28",
+ "d24", "d25", "d26", "d27", "d28", "d29"
};
return names[index];
}
static int ToAllocationIndex(FPRegister reg) {
- int code = reg.code();
- ASSERT(code < NumAllocatableRegisters());
- return code;
+ ASSERT(reg.IsAllocatable());
+ unsigned code = reg.code();
+
+ return (code <= kAllocatableLowRangeEnd)
+ ? code
+ : code - kAllocatableRangeGapSize;
}
static FPRegister from_code(int code) {
@@ -375,10 +399,10 @@
ALIAS_REGISTER(Register, xzr, x31);
ALIAS_REGISTER(Register, wzr, w31);
-// Crankshaft double scratch register.
-ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29);
// Keeps the 0 double value.
-ALIAS_REGISTER(FPRegister, fp_zero, d30);
+ALIAS_REGISTER(FPRegister, fp_zero, d15);
+// Crankshaft double scratch register.
+ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d30);
// MacroAssembler double scratch register.
ALIAS_REGISTER(FPRegister, fp_scratch, d31);
@@ -822,9 +846,6 @@
return SizeOfCodeGeneratedSince(label) / kInstructionSize;
}
- // TODO(all): Initialize these constants related with code patching.
- // TODO(all): Set to -1 to hopefully crash if mistakenly used.
-
// Number of instructions generated for the return sequence in
// FullCodeGenerator::EmitReturnSequence.
static const int kJSRetSequenceInstructions = 7;
diff --git a/src/a64/builtins-a64.cc b/src/a64/builtins-a64.cc
index 2c5fe89..c49133d 100644
--- a/src/a64/builtins-a64.cc
+++ b/src/a64/builtins-a64.cc
@@ -1042,7 +1042,7 @@
(1 << SharedFunctionInfo::kNative),
&shift_arguments);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
Register receiver = x2;
__ Sub(scratch1, argc, 1);
__ Peek(receiver, Operand(scratch1, LSL, kXRegSizeInBytesLog2));
@@ -1244,7 +1244,7 @@
// Do not transform the receiver for native functions.
__ Tbnz(x10, SharedFunctionInfo::kNative, &push_receiver);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ JumpIfSmi(receiver, &convert_receiver_to_object);
__ JumpIfRoot(receiver, Heap::kNullValueRootIndex, &use_global_receiver);
__ JumpIfRoot(receiver, Heap::kUndefinedValueRootIndex,
diff --git a/src/a64/code-stubs-a64.cc b/src/a64/code-stubs-a64.cc
index 3ed79a4..7e0d708 100644
--- a/src/a64/code-stubs-a64.cc
+++ b/src/a64/code-stubs-a64.cc
@@ -1182,7 +1182,6 @@
if (exponent_type_ == ON_STACK) {
FPRegister half_double = d3;
FPRegister minus_half_double = d4;
- FPRegister zero_double = d5;
// Detect square root case. Crankshaft detects constant +/-0.5 at compile
// time and uses DoMathPowHalf instead. We then skip this check for
// non-constant cases of +/-0.5 as these hardly occur.
@@ -1215,8 +1214,7 @@
// where base is -INFINITY or -0.
// Add +0 to base. This has no effect other than turning -0 into +0.
- __ Fmov(zero_double, 0.0);
- __ Fadd(base_double, base_double, zero_double);
+ __ Fadd(base_double, base_double, fp_zero);
// The operation -0+0 results in +0 in all cases except where the
// FPCR rounding mode is 'round towards minus infinity' (RM). The
// A64 simulator does not currently simulate FPCR (where the rounding
@@ -1224,18 +1222,17 @@
if (masm->emit_debug_code()) {
UseScratchRegisterScope temps(masm);
Register temp = temps.AcquireX();
- // d5 zero_double The value +0.0 as a double.
- __ Fneg(scratch0_double, zero_double);
+ __ Fneg(scratch0_double, fp_zero);
// Verify that we correctly generated +0.0 and -0.0.
// bits(+0.0) = 0x0000000000000000
// bits(-0.0) = 0x8000000000000000
- __ Fmov(temp, zero_double);
+ __ Fmov(temp, fp_zero);
__ CheckRegisterIsClear(temp, kCouldNotGenerateZero);
__ Fmov(temp, scratch0_double);
__ Eor(temp, temp, kDSignMask);
__ CheckRegisterIsClear(temp, kCouldNotGenerateNegativeZero);
// Check that -0.0 + 0.0 == +0.0.
- __ Fadd(scratch0_double, scratch0_double, zero_double);
+ __ Fadd(scratch0_double, scratch0_double, fp_zero);
__ Fmov(temp, scratch0_double);
__ CheckRegisterIsClear(temp, kExpectedPositiveZero);
}
@@ -1793,6 +1790,9 @@
ProfileEntryHookStub::MaybeCallEntryHook(masm);
+ // Set up the reserved register for 0.0.
+ __ Fmov(fp_zero, 0.0);
+
// Build an entry frame (see layout below).
Isolate* isolate = masm->isolate();
@@ -2303,7 +2303,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
// Stack layout on entry.
// jssp[0]: number of parameters (tagged)
// jssp[8]: address of receiver argument
@@ -2333,7 +2333,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// Stack layout on entry.
// jssp[0]: number of parameters (tagged)
// jssp[8]: address of receiver argument
@@ -2419,7 +2419,8 @@
// 2. Add the size of the backing store and arguments object.
__ Add(size, size, Operand(arg_count, LSL, kPointerSizeLog2));
- __ Add(size, size, FixedArray::kHeaderSize + Heap::kArgumentsObjectSize);
+ __ Add(size, size,
+ FixedArray::kHeaderSize + Heap::kSloppyArgumentsObjectSize);
// Do the allocation of all three objects in one go. Assign this to x0, as it
// will be returned to the caller.
@@ -2446,8 +2447,9 @@
__ Ldr(global_ctx, FieldMemOperand(global_object,
GlobalObject::kNativeContextOffset));
- __ Ldr(args_offset, ContextMemOperand(global_ctx,
- Context::ARGUMENTS_BOILERPLATE_INDEX));
+ __ Ldr(args_offset,
+ ContextMemOperand(global_ctx,
+ Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX));
__ Ldr(aliased_args_offset,
ContextMemOperand(global_ctx,
Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX));
@@ -2486,7 +2488,7 @@
// x14 recv_arg pointer to receiver arguments
Register elements = x5;
- __ Add(elements, alloc_obj, Heap::kArgumentsObjectSize);
+ __ Add(elements, alloc_obj, Heap::kSloppyArgumentsObjectSize);
__ Str(elements, FieldMemOperand(alloc_obj, JSObject::kElementsOffset));
// Initialize parameter map. If there are no mapped arguments, we're done.
@@ -2498,7 +2500,7 @@
__ CmovX(backing_store, elements, eq);
__ B(eq, &skip_parameter_map);
- __ LoadRoot(x10, Heap::kNonStrictArgumentsElementsMapRootIndex);
+ __ LoadRoot(x10, Heap::kSloppyArgumentsElementsMapRootIndex);
__ Str(x10, FieldMemOperand(elements, FixedArray::kMapOffset));
__ Add(x10, mapped_params, 2);
__ SmiTag(x10);
@@ -2651,7 +2653,7 @@
__ Add(size, param_count, FixedArray::kHeaderSize / kPointerSize);
__ Cmp(param_count, 0);
__ CzeroX(size, eq);
- __ Add(size, size, Heap::kArgumentsObjectSizeStrict / kPointerSize);
+ __ Add(size, size, Heap::kStrictArgumentsObjectSize / kPointerSize);
// Do the allocation of both objects in one go. Assign this to x0, as it will
// be returned to the caller.
@@ -2668,7 +2670,7 @@
GlobalObject::kNativeContextOffset));
__ Ldr(args_offset,
ContextMemOperand(global_ctx,
- Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX));
+ Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX));
// x0 alloc_obj pointer to allocated objects: parameter array and
// arguments object
@@ -2695,7 +2697,7 @@
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
Register elements = x5;
- __ Add(elements, alloc_obj, Heap::kArgumentsObjectSizeStrict);
+ __ Add(elements, alloc_obj, Heap::kStrictArgumentsObjectSize);
__ Str(elements, FieldMemOperand(alloc_obj, JSObject::kElementsOffset));
__ LoadRoot(x10, Heap::kFixedArrayMapRootIndex);
__ Str(x10, FieldMemOperand(elements, FixedArray::kMapOffset));
@@ -3405,7 +3407,7 @@
__ Tbnz(w4, SharedFunctionInfo::kNative, &cont);
}
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ Peek(x3, argc_ * kPointerSize);
if (NeedsChecks()) {
@@ -4939,8 +4941,7 @@
void StubFailureTrampolineStub::Generate(MacroAssembler* masm) {
- // TODO(jbramley): The ARM code leaves the (shifted) offset in r1. Why?
- CEntryStub ces(1, kSaveFPRegs);
+ CEntryStub ces(1, fp_registers_ ? kSaveFPRegs : kDontSaveFPRegs);
__ Call(ces.GetCode(masm->isolate()), RelocInfo::CODE_TARGET);
int parameter_count_offset =
StubFailureTrampolineFrame::kCallerStackParameterCountFrameOffset;
diff --git a/src/a64/codegen-a64.cc b/src/a64/codegen-a64.cc
index f008494..6a2fa5b 100644
--- a/src/a64/codegen-a64.cc
+++ b/src/a64/codegen-a64.cc
@@ -546,13 +546,11 @@
// Continue the common case first. 'mi' tests N == 1.
__ B(&result_is_finite_non_zero, mi);
- // TODO(jbramley): Add (and use) a zero D register for A64.
// TODO(jbramley): Consider adding a +infinity register for A64.
__ Ldr(double_temp2, ExpConstant(constants, 2)); // Synthesize +infinity.
- __ Fsub(double_temp1, double_temp1, double_temp1); // Synthesize +0.0.
// Select between +0.0 and +infinity. 'lo' tests C == 0.
- __ Fcsel(result, double_temp1, double_temp2, lo);
+ __ Fcsel(result, fp_zero, double_temp2, lo);
// Select between {+0.0 or +infinity} and input. 'vc' tests V == 0.
__ Fcsel(result, result, input, vc);
__ B(&done);
diff --git a/src/a64/deoptimizer-a64.cc b/src/a64/deoptimizer-a64.cc
index af1a48c..58bd2d9 100644
--- a/src/a64/deoptimizer-a64.cc
+++ b/src/a64/deoptimizer-a64.cc
@@ -149,7 +149,7 @@
// Save all allocatable floating point registers.
CPURegList saved_fp_registers(CPURegister::kFPRegister, kDRegSize,
- 0, FPRegister::NumAllocatableRegisters() - 1);
+ FPRegister::kAllocatableFPRegisters);
__ PushCPURegList(saved_fp_registers);
// We save all the registers expcept jssp, sp and lr.
diff --git a/src/a64/full-codegen-a64.cc b/src/a64/full-codegen-a64.cc
index 7760530..369d8ac 100644
--- a/src/a64/full-codegen-a64.cc
+++ b/src/a64/full-codegen-a64.cc
@@ -143,10 +143,10 @@
}
#endif
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
- if (info->is_classic_mode() && !info->is_native()) {
+ if (info->strict_mode() == SLOPPY && !info->is_native()) {
Label ok;
int receiver_offset = info->scope()->num_parameters() * kXRegSizeInBytes;
__ Peek(x10, receiver_offset);
@@ -249,12 +249,12 @@
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
- if (!is_classic_mode()) {
+ if (strict_mode() == STRICT) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (function()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
+ type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
- type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
+ type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
@@ -279,7 +279,7 @@
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableDeclaration* function = scope()->function();
ASSERT(function->proxy()->var()->mode() == CONST ||
- function->proxy()->var()->mode() == CONST_HARMONY);
+ function->proxy()->var()->mode() == CONST_LEGACY);
ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
@@ -790,7 +790,7 @@
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
- bool hole_init = (mode == CONST) || (mode == CONST_HARMONY) || (mode == LET);
+ bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
case Variable::UNALLOCATED:
@@ -1320,7 +1320,7 @@
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->language_mode(), info->is_generator());
+ FastNewClosureStub stub(info->strict_mode(), info->is_generator());
__ Mov(x2, Operand(info));
__ CallStub(&stub);
} else {
@@ -1350,7 +1350,7 @@
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ Cbnz(temp, slow);
@@ -1362,7 +1362,7 @@
}
// If no outer scope calls eval, we do not need to check more
// context extensions.
- if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
+ if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
s = s->outer_scope();
}
@@ -1400,7 +1400,7 @@
for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
__ Cbnz(temp, slow);
@@ -1436,13 +1436,12 @@
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == LET ||
- local->mode() == CONST ||
- local->mode() == CONST_HARMONY) {
+ if (local->mode() == LET || local->mode() == CONST ||
+ local->mode() == CONST_LEGACY) {
__ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done);
- if (local->mode() == CONST) {
+ if (local->mode() == CONST_LEGACY) {
__ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
- } else { // LET || CONST_HARMONY
+ } else { // LET || CONST
__ Mov(x0, Operand(var->name()));
__ Push(x0);
__ CallRuntime(Runtime::kThrowReferenceError, 1);
@@ -1509,7 +1508,7 @@
// Check that we always have valid source position.
ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
ASSERT(proxy->position() != RelocInfo::kNoPosition);
- skip_init_check = var->mode() != CONST &&
+ skip_init_check = var->mode() != CONST_LEGACY &&
var->initializer_position() < proxy->position();
}
@@ -1518,7 +1517,7 @@
GetVar(x0, var);
Label done;
__ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done);
- if (var->mode() == LET || var->mode() == CONST_HARMONY) {
+ if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ Mov(x0, Operand(var->name()));
@@ -1527,7 +1526,7 @@
__ Bind(&done);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
- ASSERT(var->mode() == CONST);
+ ASSERT(var->mode() == CONST_LEGACY);
__ LoadRoot(x0, Heap::kUndefinedValueRootIndex);
__ Bind(&done);
}
@@ -2136,7 +2135,7 @@
VisitForAccumulatorValue(prop->key());
__ Mov(x1, x0);
__ Pop(x2, x0);
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic);
@@ -2161,9 +2160,9 @@
void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, LanguageMode mode) {
+ Handle<String> name, StrictMode strict_mode) {
__ Mov(x11, Operand(name));
- __ Mov(x10, Operand(Smi::FromInt(mode)));
+ __ Mov(x10, Operand(Smi::FromInt(strict_mode)));
// jssp[0] : mode.
// jssp[8] : name.
// jssp[16] : context.
@@ -2182,7 +2181,7 @@
__ Ldr(x1, GlobalObjectMemOperand());
CallStoreIC();
- } else if (op == Token::INIT_CONST) {
+ } else if (op == Token::INIT_CONST_LEGACY) {
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
@@ -2203,7 +2202,7 @@
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
@@ -2218,11 +2217,11 @@
EmitStoreToStackLocalOrContextSlot(var, location);
}
- } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
+ } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
// Assignment to var or initializing assignment to let/const
// in harmony mode.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
MemOperand location = VarOperand(var, x1);
@@ -2266,7 +2265,7 @@
// TODO(all): Could we pass this in registers rather than on the stack?
__ Pop(x1, x2); // Key and object holding the property.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->AssignmentFeedbackId());
@@ -2320,7 +2319,7 @@
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
- // is a classic mode method.
+ // is a sloppy mode method.
__ Push(isolate()->factory()->undefined_value());
flags = NO_CALL_FUNCTION_FLAGS;
} else {
@@ -2441,7 +2440,7 @@
__ Push(x10, x11);
// Prepare to push the language mode.
- __ Mov(x10, Operand(Smi::FromInt(language_mode())));
+ __ Mov(x10, Operand(Smi::FromInt(strict_mode())));
// Prepare to push the start position of the scope the calls resides in.
__ Mov(x11, Operand(Smi::FromInt(scope()->start_position())));
@@ -3878,9 +3877,7 @@
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
- __ Mov(x10, Operand(Smi::FromInt(strict_mode_flag)));
+ __ Mov(x10, Operand(Smi::FromInt(strict_mode())));
__ Push(x10);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(x0);
@@ -3888,11 +3885,11 @@
Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
// but "delete this" is allowed.
- ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
+ ASSERT(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
__ Ldr(x12, GlobalObjectMemOperand());
__ Mov(x11, Operand(var->name()));
- __ Mov(x10, Operand(Smi::FromInt(kNonStrictMode)));
+ __ Mov(x10, Operand(Smi::FromInt(SLOPPY)));
__ Push(x12, x11, x10);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(x0);
@@ -4149,7 +4146,7 @@
case KEYED_PROPERTY: {
__ Pop(x1); // Key.
__ Pop(x2); // Receiver.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->CountStoreFeedbackId());
diff --git a/src/a64/ic-a64.cc b/src/a64/ic-a64.cc
index 73d4013..18677f7 100644
--- a/src/a64/ic-a64.cc
+++ b/src/a64/ic-a64.cc
@@ -369,7 +369,7 @@
__ Tbnz(key, kXSignBit, slow_case);
// Load the elements object and check its map.
- Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
+ Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
__ Ldr(map, FieldMemOperand(object, JSObject::kElementsOffset));
__ CheckMap(map, scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
@@ -474,12 +474,8 @@
__ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4);
- // TODO(jbramley): Does the target actually expect an argument in x3, or is
- // this inherited from ARM's push semantics?
- __ Mov(x3, x0);
- __ Push(x3, x2);
-
// Perform tail call to the entry.
+ __ Push(x0, x2);
ExternalReference ref =
ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
__ TailCallExternalReference(ref, 2, 1);
@@ -493,16 +489,12 @@
// -- x0 : receiver
// -----------------------------------
- // TODO(jbramley): Does the target actually expect an argument in x3, or is
- // this inherited from ARM's push semantics?
- __ Mov(x3, x0);
- __ Push(x3, x2);
-
+ __ Push(x0, x2);
__ TailCallRuntime(Runtime::kGetProperty, 2, 1);
}
-void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- lr : return address
// -- x0 : key
@@ -534,8 +526,8 @@
}
-void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
- ASM_LOCATION("KeyedStoreIC::GenerateNonStrictArguments");
+void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
+ ASM_LOCATION("KeyedStoreIC::GenerateSloppyArguments");
// ---------- S t a t e --------------
// -- lr : return address
// -- x0 : value
@@ -930,7 +922,7 @@
void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ASM_LOCATION("KeyedStoreIC::GenerateRuntimeSetProperty");
// ---------- S t a t e --------------
// -- x0 : value
@@ -985,8 +977,6 @@
// We have to go to the runtime if the current value is the hole because there
// may be a callback on the element.
Label holecheck_passed;
- // TODO(all): This address calculation is repeated later (for the store
- // itself). We should keep the result to avoid doing the work twice.
__ Add(x10, elements, FixedArray::kHeaderSize - kHeapObjectTag);
__ Add(x10, x10, Operand::UntagSmiAndScale(key, kPointerSizeLog2));
__ Ldr(x11, MemOperand(x10));
@@ -1039,8 +1029,6 @@
// HOLECHECK: guards "A[i] double hole?"
// We have to see if the double version of the hole is present. If so go to
// the runtime.
- // TODO(all): This address calculation was done earlier. We should keep the
- // result to avoid doing the work twice.
__ Add(x10, elements, FixedDoubleArray::kHeaderSize - kHeapObjectTag);
__ Add(x10, x10, Operand::UntagSmiAndScale(key, kPointerSizeLog2));
__ Ldr(x11, MemOperand(x10));
@@ -1117,7 +1105,7 @@
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ASM_LOCATION("KeyedStoreIC::GenerateGeneric");
// ---------- S t a t e --------------
// -- x0 : value
@@ -1283,7 +1271,7 @@
void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ASM_LOCATION("StoreIC::GenerateRuntimeSetProperty");
// ----------- S t a t e -------------
// -- x0 : value
diff --git a/src/a64/lithium-a64.cc b/src/a64/lithium-a64.cc
index dff7003..2f2061f 100644
--- a/src/a64/lithium-a64.cc
+++ b/src/a64/lithium-a64.cc
@@ -506,15 +506,6 @@
instr->MarkAsCall();
instr = AssignPointerMap(instr);
- if (hinstr->HasObservableSideEffects()) {
- ASSERT(hinstr->next()->IsSimulate());
- HSimulate* sim = HSimulate::cast(hinstr->next());
- ASSERT(instruction_pending_deoptimization_environment_ == NULL);
- ASSERT(pending_deoptimization_ast_id_.IsNone());
- instruction_pending_deoptimization_environment_ = instr;
- pending_deoptimization_ast_id_ = sim->ast_id();
- }
-
// If instruction does not have side-effects lazy deoptimization
// after the call will try to deoptimize to the point before the call.
// Thus we still need to attach environment to this call even if
@@ -736,6 +727,26 @@
instr = AssignEnvironment(instr);
}
chunk_->AddInstruction(instr, current_block_);
+
+ if (instr->IsCall()) {
+ HValue* hydrogen_value_for_lazy_bailout = current;
+ LInstruction* instruction_needing_environment = NULL;
+ if (current->HasObservableSideEffects()) {
+ HSimulate* sim = HSimulate::cast(current->next());
+ instruction_needing_environment = instr;
+ sim->ReplayEnvironment(current_block_->last_environment());
+ hydrogen_value_for_lazy_bailout = sim;
+ }
+ LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
+ bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
+ chunk_->AddInstruction(bailout, current_block_);
+ if (instruction_needing_environment != NULL) {
+ // Store the lazy deopt environment with the instruction if needed.
+ // Right now it is only used for LInstanceOfKnownGlobal.
+ instruction_needing_environment->
+ SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
+ }
+ }
}
current_instruction_ = old_current;
}
@@ -1374,16 +1385,15 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor));
- bool can_deopt =
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- (instr->CheckFlag(HValue::kCanOverflow) &&
- instr->left()->RangeCanInclude(kMinInt) && divisor == -1) ||
+ LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
+ dividend, divisor));
+ if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
(!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
- divisor != 1 && divisor != -1);
- return can_deopt ? AssignEnvironment(result) : result;
+ divisor != 1 && divisor != -1)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1393,16 +1403,16 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- bool truncating = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
- LOperand* temp = truncating ? NULL : TempRegister();
- LInstruction* result =
- DefineAsRegister(new(zone()) LDivByConstI(dividend, divisor, temp));
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- !truncating;
- return can_deopt ? AssignEnvironment(result) : result;
+ LOperand* temp = instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)
+ ? NULL : TempRegister();
+ LInstruction* result = DefineAsRegister(new(zone()) LDivByConstI(
+ dividend, divisor, temp));
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1760,8 +1770,7 @@
DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
bool can_deopt =
divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0);
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
return can_deopt ? AssignEnvironment(result) : result;
}
@@ -1812,12 +1821,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegisterAtStart(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
- bool can_deopt =
- instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative();
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
+ dividend, divisor));
+ if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1828,13 +1837,12 @@
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp = TempRegister();
- LInstruction* result =
- DefineAsRegister(new(zone()) LModByConstI(dividend, divisor, temp));
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative());
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineAsRegister(new(zone()) LModByConstI(
+ dividend, divisor, temp));
+ if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1844,12 +1852,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = UseRegister(instr->right());
- LInstruction* result =
- DefineAsRegister(new(zone()) LModI(dividend, divisor));
- bool can_deopt = (instr->right()->CanBeZero() ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative() && instr->CanBeZero()));
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineAsRegister(new(zone()) LModI(dividend, divisor));
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1909,8 +1917,7 @@
// allocated for the second operand.
LInstruction* result;
if (instr->representation().IsSmi()) {
- // TODO(jbramley/rmcilroy): Fix LMulS so we can UseRegisterAtStart here.
- LOperand* right = UseRegister(most_const);
+ LOperand* right = UseRegisterAtStart(most_const);
result = DefineAsRegister(new(zone()) LMulS(left, right));
} else {
LOperand* right = UseRegisterAtStart(most_const);
@@ -2110,21 +2117,6 @@
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
instr->ReplayEnvironment(current_block_->last_environment());
-
- // If there is an instruction pending deoptimization environment create a
- // lazy bailout instruction to capture the environment.
- if (pending_deoptimization_ast_id_ == instr->ast_id()) {
- LInstruction* result = new(zone()) LLazyBailout;
- result = AssignEnvironment(result);
- // Store the lazy deopt environment with the instruction if needed. Right
- // now it is only used for LInstanceOfKnownGlobal.
- instruction_pending_deoptimization_environment_->
- SetDeferredLazyDeoptimizationEnvironment(result->environment());
- instruction_pending_deoptimization_environment_ = NULL;
- pending_deoptimization_ast_id_ = BailoutId::None();
- return result;
- }
-
return NULL;
}
@@ -2239,17 +2231,29 @@
LInstruction* LChunkBuilder::DoStoreNamedField(HStoreNamedField* instr) {
- // TODO(jbramley): Optimize register usage in this instruction. For now, it
- // allocates everything that it might need because it keeps changing in the
- // merge and keeping it valid is time-consuming.
-
// TODO(jbramley): It might be beneficial to allow value to be a constant in
// some cases. x64 makes use of this with FLAG_track_fields, for example.
LOperand* object = UseRegister(instr->object());
- LOperand* value = UseRegisterAndClobber(instr->value());
- LOperand* temp0 = TempRegister();
- LOperand* temp1 = TempRegister();
+ LOperand* value;
+ LOperand* temp0 = NULL;
+ LOperand* temp1 = NULL;
+
+ if (instr->access().IsExternalMemory() ||
+ instr->field_representation().IsDouble()) {
+ value = UseRegister(instr->value());
+ } else if (instr->NeedsWriteBarrier()) {
+ value = UseRegisterAndClobber(instr->value());
+ temp0 = TempRegister();
+ temp1 = TempRegister();
+ } else if (instr->NeedsWriteBarrierForMap()) {
+ value = UseRegister(instr->value());
+ temp0 = TempRegister();
+ temp1 = TempRegister();
+ } else {
+ value = UseRegister(instr->value());
+ temp0 = TempRegister();
+ }
LStoreNamedField* result =
new(zone()) LStoreNamedField(object, value, temp0, temp1);
diff --git a/src/a64/lithium-a64.h b/src/a64/lithium-a64.h
index 6f718e5..cb222bf 100644
--- a/src/a64/lithium-a64.h
+++ b/src/a64/lithium-a64.h
@@ -1335,8 +1335,6 @@
LOperand* right() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
- bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
-
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
};
@@ -2490,7 +2488,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2539,7 +2537,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2978,9 +2976,7 @@
status_(UNUSED),
current_instruction_(NULL),
current_block_(NULL),
- allocator_(allocator),
- instruction_pending_deoptimization_environment_(NULL),
- pending_deoptimization_ast_id_(BailoutId::None()) { }
+ allocator_(allocator) { }
// Build the sequence for the graph.
LPlatformChunk* Build();
@@ -3117,8 +3113,6 @@
HInstruction* current_instruction_;
HBasicBlock* current_block_;
LAllocator* allocator_;
- LInstruction* instruction_pending_deoptimization_environment_;
- BailoutId pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};
diff --git a/src/a64/lithium-codegen-a64.cc b/src/a64/lithium-codegen-a64.cc
index ea826d6..96e5cd3 100644
--- a/src/a64/lithium-codegen-a64.cc
+++ b/src/a64/lithium-codegen-a64.cc
@@ -668,11 +668,11 @@
// TODO(all): Add support for stop_t FLAG in DEBUG mode.
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
if (info_->this_has_uses() &&
- info_->is_classic_mode() &&
+ info_->strict_mode() == SLOPPY &&
!info_->is_native()) {
Label ok;
int receiver_offset = info_->scope()->num_parameters() * kXRegSizeInBytes;
@@ -771,6 +771,13 @@
}
+void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
+ if (!instr->IsLazyBailout() && !instr->IsGap()) {
+ safepoints_.BumpLastLazySafepointIndex();
+ }
+}
+
+
bool LCodeGen::GenerateDeferredCode() {
ASSERT(is_generating());
if (deferred_.length() > 0) {
@@ -2607,14 +2614,12 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ Cmp(dividend, 0);
DeoptimizeIf(eq, instr->environment());
}
// Check for (kMinInt / -1).
- if (hdiv->CheckFlag(HValue::kCanOverflow) &&
- hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) {
+ if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ Cmp(dividend, kMinInt);
DeoptimizeIf(eq, instr->environment());
}
@@ -2657,8 +2662,7 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIfZero(dividend, instr->environment());
}
@@ -2678,16 +2682,16 @@
void LCodeGen::DoDivI(LDivI* instr) {
+ HBinaryOperation* hdiv = instr->hydrogen();
Register dividend = ToRegister32(instr->left());
Register divisor = ToRegister32(instr->right());
Register result = ToRegister32(instr->result());
- HValue* hdiv = instr->hydrogen_value();
// Issue the division first, and then check for any deopt cases whilst the
// result is computed.
__ Sdiv(result, dividend, divisor);
- if (hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ if (hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
ASSERT_EQ(NULL, instr->temp());
return;
}
@@ -2779,7 +2783,7 @@
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(instr->hydrogen()->language_mode(),
+ FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
instr->hydrogen()->is_generator());
__ Mov(x2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
@@ -3472,7 +3476,7 @@
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -3735,8 +3739,7 @@
Register input = ToRegister(instr->value());
__ JumpIfSmi(result, &result_ok);
__ Cmp(input, result);
- // TODO(all): Shouldn't we assert here?
- DeoptimizeIf(ne, instr->environment());
+ __ Assert(eq, kUnexpectedValue);
__ Bind(&result_ok);
}
@@ -3895,8 +3898,7 @@
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ Cmp(dividend, 0);
DeoptimizeIf(eq, instr->environment());
}
@@ -3983,9 +3985,7 @@
__ B(&done, eq);
// Add +0.0 to convert -0.0 to +0.0.
- // TODO(jbramley): A constant zero register would be helpful here.
- __ Fmov(double_scratch(), 0.0);
- __ Fadd(double_scratch(), input, double_scratch());
+ __ Fadd(double_scratch(), input, fp_zero);
__ Fsqrt(result, double_scratch());
__ Bind(&done);
@@ -4184,8 +4184,7 @@
// Check for negative zero.
HMod* hmod = instr->hydrogen();
- if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hmod->left()->CanBeNegative()) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ Cbnz(result, &remainder_not_zero);
DeoptimizeIfNegative(dividend, instr->environment());
@@ -4202,7 +4201,7 @@
Label deopt, done;
// modulo = dividend - quotient * divisor
__ Sdiv(result, dividend, divisor);
- if (instr->hydrogen()->right()->CanBeZero()) {
+ if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
// Combine the deoptimization sites.
Label ok;
__ Cbnz(divisor, &ok);
@@ -4211,9 +4210,7 @@
__ Bind(&ok);
}
__ Msub(result, result, divisor, dividend);
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->hydrogen()->left()->CanBeNegative() &&
- instr->hydrogen()->CanBeZero()) {
+ if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Cbnz(result, &done);
if (deopt.is_bound()) { // TODO(all) This is a hack, remove this...
__ Tbnz(dividend, kWSignBit, &deopt);
@@ -4328,7 +4325,7 @@
bool bailout_on_minus_zero =
instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
- if (bailout_on_minus_zero) {
+ if (bailout_on_minus_zero && !left.Is(right)) {
// If one operand is zero and the other is negative, the result is -0.
// - Set Z (eq) if either left or right, or both, are 0.
__ Cmp(left, 0);
@@ -4358,7 +4355,7 @@
bool bailout_on_minus_zero =
instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
- if (bailout_on_minus_zero) {
+ if (bailout_on_minus_zero && !left.Is(right)) {
// If one operand is zero and the other is negative, the result is -0.
// - Set Z (eq) if either left or right, or both, are 0.
__ Cmp(left, 0);
@@ -4376,10 +4373,25 @@
__ SmiTag(result);
DeoptimizeIf(ne, instr->environment());
} else {
- // TODO(jbramley): This could be rewritten to support UseRegisterAtStart.
- ASSERT(!AreAliased(result, right));
- __ SmiUntag(result, left);
- __ Mul(result, result, right);
+ if (AreAliased(result, left, right)) {
+ // All three registers are the same: half untag the input and then
+ // multiply, giving a tagged result.
+ STATIC_ASSERT((kSmiShift % 2) == 0);
+ __ Asr(result, left, kSmiShift / 2);
+ __ Mul(result, result, result);
+ } else if (result.Is(left) && !left.Is(right)) {
+ // Registers result and left alias, right is distinct: untag left into
+ // result, and then multiply by right, giving a tagged result.
+ __ SmiUntag(result, left);
+ __ Mul(result, result, right);
+ } else {
+ ASSERT(!left.Is(result));
+ // Registers result and right alias, left is distinct, or all registers
+ // are distinct: untag right into result, and then multiply by left,
+ // giving a tagged result.
+ __ SmiUntag(result, right);
+ __ Mul(result, left, result);
+ }
}
}
@@ -5074,7 +5086,7 @@
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -5175,43 +5187,27 @@
ASSERT(ToRegister(instr->key()).Is(x1));
ASSERT(ToRegister(instr->value()).Is(x0));
- Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+ Handle<Code> ic = instr->strict_mode() == STRICT
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
-// TODO(jbramley): Once the merge is done and we're tracking bleeding_edge, try
-// to tidy up this function.
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Representation representation = instr->representation();
Register object = ToRegister(instr->object());
- Register temp0 = ToRegister(instr->temp0());
- Register temp1 = ToRegister(instr->temp1());
HObjectAccess access = instr->hydrogen()->access();
+ Handle<Map> transition = instr->transition();
int offset = access.offset();
if (access.IsExternalMemory()) {
+ ASSERT(transition.is_null());
+ ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
Register value = ToRegister(instr->value());
__ Store(value, MemOperand(object, offset), representation);
return;
- }
-
- Handle<Map> transition = instr->transition();
- SmiCheck check_needed =
- instr->hydrogen()->value()->IsHeapObject()
- ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
-
- if (representation.IsHeapObject()) {
- Register value = ToRegister(instr->value());
- if (!instr->hydrogen()->value()->type().IsHeapObject()) {
- DeoptimizeIfSmi(value, instr->environment());
-
- // We know that value is a smi now, so we can omit the check below.
- check_needed = OMIT_SMI_CHECK;
- }
} else if (representation.IsDouble()) {
ASSERT(transition.is_null());
ASSERT(access.IsInobject());
@@ -5221,9 +5217,22 @@
return;
}
+ Register value = ToRegister(instr->value());
+
+ SmiCheck check_needed = instr->hydrogen()->value()->IsHeapObject()
+ ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
+
+ if (representation.IsHeapObject() &&
+ !instr->hydrogen()->value()->type().IsHeapObject()) {
+ DeoptimizeIfSmi(value, instr->environment());
+
+ // We know that value is a smi now, so we can omit the check below.
+ check_needed = OMIT_SMI_CHECK;
+ }
+
if (!transition.is_null()) {
// Store the new map value.
- Register new_map_value = temp0;
+ Register new_map_value = ToRegister(instr->temp0());
__ Mov(new_map_value, Operand(transition));
__ Str(new_map_value, FieldMemOperand(object, HeapObject::kMapOffset));
if (instr->hydrogen()->NeedsWriteBarrierForMap()) {
@@ -5231,7 +5240,7 @@
__ RecordWriteField(object,
HeapObject::kMapOffset,
new_map_value,
- temp1,
+ ToRegister(instr->temp1()),
GetLinkRegisterState(),
kSaveFPRegs,
OMIT_REMEMBERED_SET,
@@ -5240,21 +5249,28 @@
}
// Do the store.
- Register value = ToRegister(instr->value());
Register destination;
if (access.IsInobject()) {
destination = object;
} else {
+ Register temp0 = ToRegister(instr->temp0());
__ Ldr(temp0, FieldMemOperand(object, JSObject::kPropertiesOffset));
destination = temp0;
}
if (representation.IsSmi() &&
- instr->hydrogen()->value()->representation().IsInteger32()) {
+ instr->hydrogen()->value()->representation().IsInteger32()) {
ASSERT(instr->hydrogen()->store_mode() == STORE_TO_INITIALIZED_ENTRY);
#ifdef DEBUG
- __ Ldr(temp1, FieldMemOperand(destination, offset));
- __ AssertSmi(temp1);
+ Register temp0 = ToRegister(instr->temp0());
+ __ Ldr(temp0, FieldMemOperand(destination, offset));
+ __ AssertSmi(temp0);
+ // If destination aliased temp0, restore it to the address calculated
+ // earlier.
+ if (destination.Is(temp0)) {
+ ASSERT(!access.IsInobject());
+ __ Ldr(destination, FieldMemOperand(object, JSObject::kPropertiesOffset));
+ }
#endif
STATIC_ASSERT(kSmiValueSize == 32 && kSmiShift == 32 && kSmiTag == 0);
__ Store(value, UntagSmiFieldMemOperand(destination, offset),
@@ -5265,8 +5281,8 @@
if (instr->hydrogen()->NeedsWriteBarrier()) {
__ RecordWriteField(destination,
offset,
- value, // Clobbered.
- temp1, // Clobbered.
+ value, // Clobbered.
+ ToRegister(instr->temp1()), // Clobbered.
GetLinkRegisterState(),
kSaveFPRegs,
EMIT_REMEMBERED_SET,
@@ -5282,8 +5298,7 @@
// Name must be in x2.
__ Mov(x2, Operand(instr->name()));
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag());
+ Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
diff --git a/src/a64/lithium-codegen-a64.h b/src/a64/lithium-codegen-a64.h
index 140b1ae..fb1ca94 100644
--- a/src/a64/lithium-codegen-a64.h
+++ b/src/a64/lithium-codegen-a64.h
@@ -276,6 +276,7 @@
void RestoreCallerDoubles();
// Code generation steps. Returns true if code generation should continue.
+ void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE;
bool GeneratePrologue();
bool GenerateDeferredCode();
bool GenerateDeoptJumpTable();
diff --git a/src/a64/macro-assembler-a64.cc b/src/a64/macro-assembler-a64.cc
index 2bc2128..4b6b8eb 100644
--- a/src/a64/macro-assembler-a64.cc
+++ b/src/a64/macro-assembler-a64.cc
@@ -1516,12 +1516,7 @@
void MacroAssembler::AssertName(Register object) {
if (emit_debug_code()) {
- STATIC_ASSERT(kSmiTag == 0);
- // TODO(jbramley): Add AbortIfSmi and related functions.
- Label not_smi;
- JumpIfNotSmi(object, ¬_smi);
- Abort(kOperandIsASmiAndNotAName);
- Bind(¬_smi);
+ AssertNotSmi(object, kOperandIsASmiAndNotAName);
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
@@ -1763,11 +1758,13 @@
}
-void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
- ASSERT(!target.is(x1));
- GetBuiltinFunction(x1, id);
+void MacroAssembler::GetBuiltinEntry(Register target,
+ Register function,
+ Builtins::JavaScript id) {
+ ASSERT(!AreAliased(target, function));
+ GetBuiltinFunction(function, id);
// Load the code entry point from the builtins object.
- Ldr(target, FieldMemOperand(x1, JSFunction::kCodeEntryOffset));
+ Ldr(target, FieldMemOperand(function, JSFunction::kCodeEntryOffset));
}
@@ -1778,7 +1775,8 @@
// You can't call a builtin without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
- GetBuiltinEntry(x2, id);
+ // Get the builtin entry in x2 and setup the function object in x1.
+ GetBuiltinEntry(x2, x1, id);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(x2));
Call(x2);
@@ -2847,8 +2845,6 @@
ASSERT(StackPointer().Is(jssp));
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
- // TODO(jbramley): Does x1 contain a JSFunction here, or does it already
- // have the special STUB smi?
__ Mov(temp, Operand(Smi::FromInt(StackFrame::STUB)));
// Compiled stubs don't age, and so they don't need the predictable code
// ageing sequence.
diff --git a/src/a64/macro-assembler-a64.h b/src/a64/macro-assembler-a64.h
index f5fa14f..a9cf189 100644
--- a/src/a64/macro-assembler-a64.h
+++ b/src/a64/macro-assembler-a64.h
@@ -1047,7 +1047,6 @@
CallRuntime(Runtime::FunctionForId(id), num_arguments, save_doubles);
}
- // TODO(all): Why does this variant save FP regs unconditionally?
void CallRuntimeSaveDoubles(Runtime::FunctionId id) {
const Runtime::Function* function = Runtime::FunctionForId(id);
CallRuntime(function, function->nargs, kSaveFPRegs);
@@ -1110,9 +1109,10 @@
const CallWrapper& call_wrapper = NullCallWrapper());
// Store the code object for the given builtin in the target register and
- // setup the function in x1.
- // TODO(all): Can we use another register than x1?
- void GetBuiltinEntry(Register target, Builtins::JavaScript id);
+ // setup the function in the function register.
+ void GetBuiltinEntry(Register target,
+ Register function,
+ Builtins::JavaScript id);
// Store the function for the given builtin in the target register.
void GetBuiltinFunction(Register target, Builtins::JavaScript id);
diff --git a/src/accessors.cc b/src/accessors.cc
index 9bc728d..ac64683 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -891,10 +891,10 @@
if (caller->shared()->bound()) {
return isolate->heap()->null_value();
}
- // Censor if the caller is not a classic mode function.
+ // Censor if the caller is not a sloppy mode function.
// Change from ES5, which used to throw, see:
// https://bugs.ecmascript.org/show_bug.cgi?id=310
- if (!caller->shared()->is_classic_mode()) {
+ if (caller->shared()->strict_mode() == STRICT) {
return isolate->heap()->null_value();
}
diff --git a/src/api.cc b/src/api.cc
index f2b4cb3..a6ff52c 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2651,6 +2651,13 @@
}
+void v8::Promise::CheckCast(Value* that) {
+ Utils::ApiCheck(that->IsPromise(),
+ "v8::Promise::Cast()",
+ "Could not convert to promise");
+}
+
+
void v8::ArrayBuffer::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
Utils::ApiCheck(obj->IsJSArrayBuffer(),
@@ -2988,7 +2995,7 @@
key_obj,
value_obj,
static_cast<PropertyAttributes>(attribs),
- i::kNonStrictMode);
+ i::SLOPPY);
has_pending_exception = obj.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, false);
return true;
@@ -3008,7 +3015,7 @@
index,
value_obj,
NONE,
- i::kNonStrictMode);
+ i::SLOPPY);
has_pending_exception = obj.is_null();
EXCEPTION_BAILOUT_CHECK(isolate, false);
return true;
@@ -5618,30 +5625,18 @@
i_isolate->date_cache()->ResetDateCache();
- i::HandleScope scope(i_isolate);
- // Get the function ResetDateCache (defined in date.js).
- i::Handle<i::String> func_name_str =
- i_isolate->factory()->InternalizeOneByteString(
- STATIC_ASCII_VECTOR("ResetDateCache"));
- i::MaybeObject* result =
- i_isolate->js_builtins_object()->GetProperty(*func_name_str);
- i::Object* object_func;
- if (!result->ToObject(&object_func)) {
+ if (!i_isolate->eternal_handles()->Exists(
+ i::EternalHandles::DATE_CACHE_VERSION)) {
return;
}
-
- if (object_func->IsJSFunction()) {
- i::Handle<i::JSFunction> func =
- i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
-
- // Call ResetDateCache(0 but expect no exceptions:
- bool caught_exception = false;
- i::Execution::TryCall(func,
- i_isolate->js_builtins_object(),
- 0,
- NULL,
- &caught_exception);
- }
+ i::Handle<i::FixedArray> date_cache_version =
+ i::Handle<i::FixedArray>::cast(i_isolate->eternal_handles()->GetSingleton(
+ i::EternalHandles::DATE_CACHE_VERSION));
+ ASSERT_EQ(1, date_cache_version->length());
+ CHECK(date_cache_version->get(0)->IsSmi());
+ date_cache_version->set(
+ 0,
+ i::Smi::FromInt(i::Smi::cast(date_cache_version->get(0))->value() + 1));
}
@@ -5743,6 +5738,124 @@
}
+bool Value::IsPromise() const {
+ i::Handle<i::Object> val = Utils::OpenHandle(this);
+ if (!i::FLAG_harmony_promises || !val->IsJSObject()) return false;
+ i::Handle<i::JSObject> obj = i::Handle<i::JSObject>::cast(val);
+ i::Isolate* isolate = obj->GetIsolate();
+ LOG_API(isolate, "IsPromise");
+ ENTER_V8(isolate);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> argv[] = { obj };
+ i::Handle<i::Object> b = i::Execution::Call(
+ isolate,
+ handle(
+ isolate->context()->global_object()->native_context()->is_promise()),
+ isolate->factory()->undefined_value(),
+ ARRAY_SIZE(argv), argv,
+ &has_pending_exception,
+ false);
+ EXCEPTION_BAILOUT_CHECK(isolate, false);
+ return b->BooleanValue();
+}
+
+
+Local<Promise> Promise::New(Isolate* v8_isolate) {
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+ LOG_API(isolate, "Promise::New");
+ ENTER_V8(isolate);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> result = i::Execution::Call(
+ isolate,
+ handle(isolate->context()->global_object()->native_context()->
+ promise_create()),
+ isolate->factory()->undefined_value(),
+ 0, NULL,
+ &has_pending_exception,
+ false);
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
+ return Local<Promise>::Cast(Utils::ToLocal(result));
+}
+
+
+void Promise::Resolve(Handle<Value> value) {
+ i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
+ i::Isolate* isolate = promise->GetIsolate();
+ LOG_API(isolate, "Promise::Resolve");
+ ENTER_V8(isolate);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
+ i::Execution::Call(
+ isolate,
+ handle(isolate->context()->global_object()->native_context()->
+ promise_resolve()),
+ isolate->factory()->undefined_value(),
+ ARRAY_SIZE(argv), argv,
+ &has_pending_exception,
+ false);
+ EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
+}
+
+
+void Promise::Reject(Handle<Value> value) {
+ i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
+ i::Isolate* isolate = promise->GetIsolate();
+ LOG_API(isolate, "Promise::Reject");
+ ENTER_V8(isolate);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
+ i::Execution::Call(
+ isolate,
+ handle(isolate->context()->global_object()->native_context()->
+ promise_reject()),
+ isolate->factory()->undefined_value(),
+ ARRAY_SIZE(argv), argv,
+ &has_pending_exception,
+ false);
+ EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
+}
+
+
+Local<Promise> Promise::Chain(Handle<Function> handler) {
+ i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
+ i::Isolate* isolate = promise->GetIsolate();
+ LOG_API(isolate, "Promise::Chain");
+ ENTER_V8(isolate);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
+ i::Handle<i::Object> result = i::Execution::Call(
+ isolate,
+ handle(isolate->context()->global_object()->native_context()->
+ promise_chain()),
+ promise,
+ ARRAY_SIZE(argv), argv,
+ &has_pending_exception,
+ false);
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
+ return Local<Promise>::Cast(Utils::ToLocal(result));
+}
+
+
+Local<Promise> Promise::Catch(Handle<Function> handler) {
+ i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
+ i::Isolate* isolate = promise->GetIsolate();
+ LOG_API(isolate, "Promise::Catch");
+ ENTER_V8(isolate);
+ EXCEPTION_PREAMBLE(isolate);
+ i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
+ i::Handle<i::Object> result = i::Execution::Call(
+ isolate,
+ handle(isolate->context()->global_object()->native_context()->
+ promise_catch()),
+ promise,
+ ARRAY_SIZE(argv), argv,
+ &has_pending_exception,
+ false);
+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
+ return Local<Promise>::Cast(Utils::ToLocal(result));
+}
+
+
bool v8::ArrayBuffer::IsExternal() const {
return Utils::OpenHandle(this)->is_external();
}
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index cf14172..610f153 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -1059,14 +1059,19 @@
}
-static bool use_movw_movt(const Operand& x, const Assembler* assembler) {
- if (Assembler::use_immediate_embedded_pointer_loads(assembler)) {
+static bool use_mov_immediate_load(const Operand& x,
+ const Assembler* assembler) {
+ if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
+ (assembler == NULL || !assembler->predictable_code_size())) {
+ // Prefer movw / movt to constant pool if it is more efficient on the CPU.
return true;
- }
- if (x.must_output_reloc_info(assembler)) {
+ } else if (x.must_output_reloc_info(assembler)) {
+ // Prefer constant pool if data is likely to be patched.
return false;
+ } else {
+ // Otherwise, use immediate load if movw / movt is available.
+ return CpuFeatures::IsSupported(ARMv7);
}
- return CpuFeatures::IsSupported(ARMv7);
}
@@ -1080,7 +1085,7 @@
// constant pool is required. For a mov instruction not setting the
// condition code additional instruction conventions can be used.
if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
- return !use_movw_movt(*this, assembler);
+ return !use_mov_immediate_load(*this, assembler);
} else {
// If this is not a mov or mvn instruction there will always an additional
// instructions - either mov or ldr. The mov might actually be two
@@ -1096,12 +1101,11 @@
}
-void Assembler::move_32_bit_immediate(Condition cond,
- Register rd,
- SBit s,
- const Operand& x) {
- if (rd.code() != pc.code() && s == LeaveCC) {
- if (use_movw_movt(x, this)) {
+void Assembler::move_32_bit_immediate(Register rd,
+ const Operand& x,
+ Condition cond) {
+ if (rd.code() != pc.code()) {
+ if (use_mov_immediate_load(x, this)) {
if (x.must_output_reloc_info(this)) {
RecordRelocInfo(x.rmode_, x.imm32_, DONT_USE_CONSTANT_POOL);
// Make sure the movw/movt doesn't get separated.
@@ -1138,20 +1142,9 @@
CHECK(!rn.is(ip)); // rn should never be ip, or will be trashed
Condition cond = Instruction::ConditionField(instr);
if ((instr & ~kCondMask) == 13*B21) { // mov, S not set
- move_32_bit_immediate(cond, rd, LeaveCC, x);
+ move_32_bit_immediate(rd, x, cond);
} else {
- if ((instr & kMovMvnMask) == kMovMvnPattern) {
- // Moves need to use a constant pool entry.
- RecordRelocInfo(x.rmode_, x.imm32_, USE_CONSTANT_POOL);
- ldr(ip, MemOperand(pc, 0), cond);
- } else if (x.must_output_reloc_info(this)) {
- // Otherwise, use most efficient form of fetching from constant pool.
- move_32_bit_immediate(cond, ip, LeaveCC, x);
- } else {
- // If this is not a mov or mvn instruction we may still be able to
- // avoid a constant pool entry by using mvn or movw.
- mov(ip, x, LeaveCC, cond);
- }
+ mov(ip, x, LeaveCC, cond);
addrmod1(instr, rn, rd, Operand(ip));
}
return;
@@ -1819,8 +1812,7 @@
if (src.must_output_reloc_info(this) ||
!fits_shifter(src.imm32_, &rotate_imm, &immed_8, NULL)) {
// Immediate operand cannot be encoded, load it first to register ip.
- RecordRelocInfo(src.rmode_, src.imm32_);
- ldr(ip, MemOperand(pc, 0), cond);
+ move_32_bit_immediate(ip, src);
msr(fields, Operand(ip), cond);
return;
}
diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h
index ccb5104..c35c80b 100644
--- a/src/arm/assembler-arm.h
+++ b/src/arm/assembler-arm.h
@@ -1292,12 +1292,6 @@
// Jump unconditionally to given label.
void jmp(Label* L) { b(L, al); }
- static bool use_immediate_embedded_pointer_loads(
- const Assembler* assembler) {
- return CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) &&
- (assembler == NULL || !assembler->predictable_code_size());
- }
-
// Check the code size generated from label to here.
int SizeOfCodeGeneratedSince(Label* label) {
return pc_offset() - label->pos();
@@ -1565,10 +1559,9 @@
inline void emit(Instr x);
// 32-bit immediate values
- void move_32_bit_immediate(Condition cond,
- Register rd,
- SBit s,
- const Operand& x);
+ void move_32_bit_immediate(Register rd,
+ const Operand& x,
+ Condition cond = al);
// Instruction generation
void addrmod1(Instr instr, Register rn, Register rd, const Operand& x);
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index e9aec8e..80512a8 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -1038,7 +1038,7 @@
__ tst(r3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
__ b(ne, &shift_arguments);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
__ ldr(r2, MemOperand(r2, -kPointerSize));
// r0: actual number of arguments
@@ -1246,7 +1246,7 @@
__ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
__ b(ne, &push_receiver);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ JumpIfSmi(r0, &call_to_object);
__ LoadRoot(r1, Heap::kNullValueRootIndex);
__ cmp(r0, r1);
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index f661ad8..558f5e1 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -2258,7 +2258,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
// sp[0] : number of parameters
// sp[4] : receiver displacement
// sp[8] : function
@@ -2282,7 +2282,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// Stack layout:
// sp[0] : number of parameters (tagged)
// sp[4] : address of receiver argument
@@ -2336,7 +2336,7 @@
__ add(r9, r9, Operand(FixedArray::kHeaderSize));
// 3. Arguments object.
- __ add(r9, r9, Operand(Heap::kArgumentsObjectSize));
+ __ add(r9, r9, Operand(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
__ Allocate(r9, r0, r3, r4, &runtime, TAG_OBJECT);
@@ -2345,7 +2345,7 @@
// r2 = argument count (tagged)
// Get the arguments boilerplate from the current native context into r4.
const int kNormalOffset =
- Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
+ Context::SlotOffset(Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX);
const int kAliasedOffset =
Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
@@ -2381,7 +2381,7 @@
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, r4 will point there, otherwise
// it will point to the backing store.
- __ add(r4, r0, Operand(Heap::kArgumentsObjectSize));
+ __ add(r4, r0, Operand(Heap::kSloppyArgumentsObjectSize));
__ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
// r0 = address of new object (tagged)
@@ -2396,7 +2396,7 @@
__ mov(r3, r4, LeaveCC, eq);
__ b(eq, &skip_parameter_map);
- __ LoadRoot(r6, Heap::kNonStrictArgumentsElementsMapRootIndex);
+ __ LoadRoot(r6, Heap::kSloppyArgumentsElementsMapRootIndex);
__ str(r6, FieldMemOperand(r4, FixedArray::kMapOffset));
__ add(r6, r1, Operand(Smi::FromInt(2)));
__ str(r6, FieldMemOperand(r4, FixedArray::kLengthOffset));
@@ -2426,7 +2426,7 @@
// r1 = mapping index (tagged)
// r3 = address of backing store (tagged)
// r4 = address of parameter map (tagged), which is also the address of new
- // object + Heap::kArgumentsObjectSize (tagged)
+ // object + Heap::kSloppyArgumentsObjectSize (tagged)
// r0 = temporary scratch (a.o., for address calculation)
// r5 = the hole value
__ jmp(¶meters_test);
@@ -2444,7 +2444,7 @@
__ b(ne, ¶meters_loop);
// Restore r0 = new object (tagged)
- __ sub(r0, r4, Operand(Heap::kArgumentsObjectSize));
+ __ sub(r0, r4, Operand(Heap::kSloppyArgumentsObjectSize));
__ bind(&skip_parameter_map);
// r0 = address of new object (tagged)
@@ -2517,7 +2517,7 @@
__ b(eq, &add_arguments_object);
__ add(r1, r1, Operand(FixedArray::kHeaderSize / kPointerSize));
__ bind(&add_arguments_object);
- __ add(r1, r1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
+ __ add(r1, r1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
// Do the allocation of both objects in one go.
__ Allocate(r1, r0, r2, r3, &runtime,
@@ -2527,7 +2527,7 @@
__ ldr(r4, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ ldr(r4, FieldMemOperand(r4, GlobalObject::kNativeContextOffset));
__ ldr(r4, MemOperand(r4, Context::SlotOffset(
- Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
+ Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX)));
// Copy the JS object part.
__ CopyFields(r0, r4, d0, JSObject::kHeaderSize / kPointerSize);
@@ -2548,7 +2548,7 @@
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
- __ add(r4, r0, Operand(Heap::kArgumentsObjectSizeStrict));
+ __ add(r4, r0, Operand(Heap::kStrictArgumentsObjectSize));
__ str(r4, FieldMemOperand(r0, JSObject::kElementsOffset));
__ LoadRoot(r3, Heap::kFixedArrayMapRootIndex);
__ str(r3, FieldMemOperand(r4, FixedArray::kMapOffset));
@@ -3134,7 +3134,7 @@
__ b(ne, &cont);
}
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ ldr(r3, MemOperand(sp, argc_ * kPointerSize));
if (NeedsChecks()) {
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 760afba..5d06701 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -145,10 +145,10 @@
}
#endif
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
- if (info->is_classic_mode() && !info->is_native()) {
+ if (info->strict_mode() == SLOPPY && !info->is_native()) {
Label ok;
int receiver_offset = info->scope()->num_parameters() * kPointerSize;
__ ldr(r2, MemOperand(sp, receiver_offset));
@@ -262,12 +262,12 @@
// The stub will rewrite receiever and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
- if (!is_classic_mode()) {
+ if (strict_mode() == STRICT) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (function()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
+ type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
- type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
+ type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
@@ -293,7 +293,7 @@
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableDeclaration* function = scope()->function();
ASSERT(function->proxy()->var()->mode() == CONST ||
- function->proxy()->var()->mode() == CONST_HARMONY);
+ function->proxy()->var()->mode() == CONST_LEGACY);
ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
@@ -790,7 +790,7 @@
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
- bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
+ bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
case Variable::UNALLOCATED:
globals_->Add(variable->name(), zone());
@@ -1325,7 +1325,7 @@
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->language_mode(), info->is_generator());
+ FastNewClosureStub stub(info->strict_mode(), info->is_generator());
__ mov(r2, Operand(info));
__ CallStub(&stub);
} else {
@@ -1355,7 +1355,7 @@
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ ldr(temp, ContextOperand(current, Context::EXTENSION_INDEX));
__ tst(temp, temp);
@@ -1368,7 +1368,7 @@
}
// If no outer scope calls eval, we do not need to check more
// context extensions.
- if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
+ if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
s = s->outer_scope();
}
@@ -1411,7 +1411,7 @@
for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ ldr(temp, ContextOperand(context, Context::EXTENSION_INDEX));
__ tst(temp, temp);
@@ -1449,13 +1449,12 @@
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ ldr(r0, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == LET ||
- local->mode() == CONST ||
- local->mode() == CONST_HARMONY) {
+ if (local->mode() == LET || local->mode() == CONST ||
+ local->mode() == CONST_LEGACY) {
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
- if (local->mode() == CONST) {
+ if (local->mode() == CONST_LEGACY) {
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
- } else { // LET || CONST_HARMONY
+ } else { // LET || CONST
__ b(ne, done);
__ mov(r0, Operand(var->name()));
__ push(r0);
@@ -1522,7 +1521,7 @@
// Check that we always have valid source position.
ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
ASSERT(proxy->position() != RelocInfo::kNoPosition);
- skip_init_check = var->mode() != CONST &&
+ skip_init_check = var->mode() != CONST_LEGACY &&
var->initializer_position() < proxy->position();
}
@@ -1530,7 +1529,7 @@
// Let and const need a read barrier.
GetVar(r0, var);
__ CompareRoot(r0, Heap::kTheHoleValueRootIndex);
- if (var->mode() == LET || var->mode() == CONST_HARMONY) {
+ if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
Label done;
@@ -1541,7 +1540,7 @@
__ bind(&done);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
- ASSERT(var->mode() == CONST);
+ ASSERT(var->mode() == CONST_LEGACY);
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex, eq);
}
context()->Plug(r0);
@@ -2438,7 +2437,7 @@
VisitForAccumulatorValue(prop->key());
__ mov(r1, r0);
__ Pop(r0, r2); // r0 = restored value.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic);
@@ -2463,24 +2462,23 @@
void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, LanguageMode mode) {
+ Handle<String> name, StrictMode strict_mode) {
__ push(r0); // Value.
__ mov(r1, Operand(name));
- __ mov(r0, Operand(Smi::FromInt(mode)));
+ __ mov(r0, Operand(Smi::FromInt(strict_mode)));
__ Push(cp, r1, r0); // Context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4);
}
-void FullCodeGenerator::EmitVariableAssignment(Variable* var,
- Token::Value op) {
+void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(r2, Operand(var->name()));
__ ldr(r1, GlobalObjectOperand());
CallStoreIC();
- } else if (op == Token::INIT_CONST) {
+ } else if (op == Token::INIT_CONST_LEGACY) {
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
@@ -2502,7 +2500,7 @@
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
@@ -2518,11 +2516,11 @@
EmitStoreToStackLocalOrContextSlot(var, location);
}
- } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
+ } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
// Assignment to var or initializing assignment to let/const
// in harmony mode.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT((var->IsStackAllocated() || var->IsContextSlot()));
MemOperand location = VarOperand(var, r1);
@@ -2564,7 +2562,7 @@
SetSourcePosition(expr->position());
__ Pop(r2, r1); // r1 = key.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->AssignmentFeedbackId());
@@ -2617,7 +2615,7 @@
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
- // is a classic mode method.
+ // is a sloppy mode method.
__ Push(isolate()->factory()->undefined_value());
flags = NO_CALL_FUNCTION_FLAGS;
} else {
@@ -2734,8 +2732,8 @@
int receiver_offset = 2 + info_->scope()->num_parameters();
__ ldr(r3, MemOperand(fp, receiver_offset * kPointerSize));
- // r2: the language mode.
- __ mov(r2, Operand(Smi::FromInt(language_mode())));
+ // r2: strict mode.
+ __ mov(r2, Operand(Smi::FromInt(strict_mode())));
// r1: the start position of the scope the calls resides in.
__ mov(r1, Operand(Smi::FromInt(scope()->start_position())));
@@ -4172,9 +4170,7 @@
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
- __ mov(r1, Operand(Smi::FromInt(strict_mode_flag)));
+ __ mov(r1, Operand(Smi::FromInt(strict_mode())));
__ push(r1);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(r0);
@@ -4182,11 +4178,11 @@
Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
// but "delete this" is allowed.
- ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
+ ASSERT(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
__ ldr(r2, GlobalObjectOperand());
__ mov(r1, Operand(var->name()));
- __ mov(r0, Operand(Smi::FromInt(kNonStrictMode)));
+ __ mov(r0, Operand(Smi::FromInt(SLOPPY)));
__ Push(r2, r1, r0);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(r0);
@@ -4440,7 +4436,7 @@
}
case KEYED_PROPERTY: {
__ Pop(r2, r1); // r1 = key. r2 = receiver.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->CountStoreFeedbackId());
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 1af6cf8..3d57105 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -427,7 +427,7 @@
__ b(ne, slow_case);
// Load the elements into scratch1 and check its map.
- Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
+ Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
__ ldr(scratch1, FieldMemOperand(object, JSObject::kElementsOffset));
__ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK);
@@ -489,7 +489,7 @@
}
-void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- lr : return address
// -- r0 : key
@@ -515,7 +515,7 @@
}
-void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- r0 : value
// -- r1 : key
@@ -876,7 +876,7 @@
void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ---------- S t a t e --------------
// -- r0 : value
// -- r1 : key
@@ -1060,7 +1060,7 @@
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ---------- S t a t e --------------
// -- r0 : value
// -- r1 : key
@@ -1219,7 +1219,7 @@
void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : receiver
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index f12b6ea..d6a4c83 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -614,15 +614,6 @@
instr->MarkAsCall();
instr = AssignPointerMap(instr);
- if (hinstr->HasObservableSideEffects()) {
- ASSERT(hinstr->next()->IsSimulate());
- HSimulate* sim = HSimulate::cast(hinstr->next());
- ASSERT(instruction_pending_deoptimization_environment_ == NULL);
- ASSERT(pending_deoptimization_ast_id_.IsNone());
- instruction_pending_deoptimization_environment_ = instr;
- pending_deoptimization_ast_id_ = sim->ast_id();
- }
-
// If instruction does not have side-effects lazy deoptimization
// after the call will try to deoptimize to the point before the call.
// Thus we still need to attach environment to this call even if
@@ -905,6 +896,26 @@
instr = AssignEnvironment(instr);
}
chunk_->AddInstruction(instr, current_block_);
+
+ if (instr->IsCall()) {
+ HValue* hydrogen_value_for_lazy_bailout = current;
+ LInstruction* instruction_needing_environment = NULL;
+ if (current->HasObservableSideEffects()) {
+ HSimulate* sim = HSimulate::cast(current->next());
+ instruction_needing_environment = instr;
+ sim->ReplayEnvironment(current_block_->last_environment());
+ hydrogen_value_for_lazy_bailout = sim;
+ }
+ LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
+ bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
+ chunk_->AddInstruction(bailout, current_block_);
+ if (instruction_needing_environment != NULL) {
+ // Store the lazy deopt environment with the instruction if needed.
+ // Right now it is only used for LInstanceOfKnownGlobal.
+ instruction_needing_environment->
+ SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
+ }
+ }
}
current_instruction_ = old_current;
}
@@ -1244,16 +1255,15 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor));
- bool can_deopt =
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- (instr->CheckFlag(HValue::kCanOverflow) &&
- instr->left()->RangeCanInclude(kMinInt) && divisor == -1) ||
+ LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
+ dividend, divisor));
+ if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
(!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
- divisor != 1 && divisor != -1);
- return can_deopt ? AssignEnvironment(result) : result;
+ divisor != 1 && divisor != -1)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1263,14 +1273,14 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LDivByConstI(dividend, divisor));
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineAsRegister(new(zone()) LDivByConstI(
+ dividend, divisor));
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1326,8 +1336,7 @@
DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
bool can_deopt =
divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0);
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
return can_deopt ? AssignEnvironment(result) : result;
}
@@ -1349,12 +1358,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegisterAtStart(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
- bool can_deopt =
- instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative();
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
+ dividend, divisor));
+ if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1364,13 +1373,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LModByConstI(dividend, divisor));
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative());
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineAsRegister(new(zone()) LModByConstI(
+ dividend, divisor));
+ if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1378,32 +1386,17 @@
ASSERT(instr->representation().IsSmiOrInteger32());
ASSERT(instr->left()->representation().Equals(instr->representation()));
ASSERT(instr->right()->representation().Equals(instr->representation()));
- if (CpuFeatures::IsSupported(SUDIV)) {
- LOperand* dividend = UseRegister(instr->left());
- LOperand* divisor = UseRegister(instr->right());
- LInstruction* result =
- DefineAsRegister(new(zone()) LModI(dividend, divisor, NULL, NULL));
- bool can_deopt = (instr->right()->CanBeZero() ||
- (instr->left()->RangeCanInclude(kMinInt) &&
- instr->right()->RangeCanInclude(-1) &&
- instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
- (instr->left()->CanBeNegative() &&
- instr->CanBeZero() &&
- instr->CheckFlag(HValue::kBailoutOnMinusZero)));
- return can_deopt ? AssignEnvironment(result) : result;
- } else {
- LOperand* dividend = UseRegister(instr->left());
- LOperand* divisor = UseRegister(instr->right());
- LOperand* temp = FixedTemp(d10);
- LOperand* temp2 = FixedTemp(d11);
- LInstruction* result =
- DefineAsRegister(new(zone()) LModI(dividend, divisor, temp, temp2));
- bool can_deopt = (instr->right()->CanBeZero() ||
- (instr->left()->CanBeNegative() &&
- instr->CanBeZero() &&
- instr->CheckFlag(HValue::kBailoutOnMinusZero)));
- return can_deopt ? AssignEnvironment(result) : result;
+ LOperand* dividend = UseRegister(instr->left());
+ LOperand* divisor = UseRegister(instr->right());
+ LOperand* temp = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d10);
+ LOperand* temp2 = CpuFeatures::IsSupported(SUDIV) ? NULL : FixedTemp(d11);
+ LInstruction* result = DefineAsRegister(new(zone()) LModI(
+ dividend, divisor, temp, temp2));
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
}
+ return result;
}
@@ -2463,21 +2456,6 @@
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
instr->ReplayEnvironment(current_block_->last_environment());
-
- // If there is an instruction pending deoptimization environment create a
- // lazy bailout instruction to capture the environment.
- if (pending_deoptimization_ast_id_ == instr->ast_id()) {
- LInstruction* result = new(zone()) LLazyBailout;
- result = AssignEnvironment(result);
- // Store the lazy deopt environment with the instruction if needed. Right
- // now it is only used for LInstanceOfKnownGlobal.
- instruction_pending_deoptimization_environment_->
- SetDeferredLazyDeoptimizationEnvironment(result->environment());
- instruction_pending_deoptimization_environment_ = NULL;
- pending_deoptimization_ast_id_ = BailoutId::None();
- return result;
- }
-
return NULL;
}
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 86cf2f2..953bd34 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -725,8 +725,6 @@
LOperand* right() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
- bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
-
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
};
@@ -2217,7 +2215,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2280,7 +2278,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2722,9 +2720,7 @@
current_instruction_(NULL),
current_block_(NULL),
next_block_(NULL),
- allocator_(allocator),
- instruction_pending_deoptimization_environment_(NULL),
- pending_deoptimization_ast_id_(BailoutId::None()) { }
+ allocator_(allocator) { }
// Build the sequence for the graph.
LPlatformChunk* Build();
@@ -2868,8 +2864,6 @@
HBasicBlock* current_block_;
HBasicBlock* next_block_;
LAllocator* allocator_;
- LInstruction* instruction_pending_deoptimization_environment_;
- BailoutId pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index b10ed59..d725c7c 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -147,11 +147,11 @@
// fp: Caller's frame pointer.
// lr: Caller's pc.
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
if (info_->this_has_uses() &&
- info_->is_classic_mode() &&
+ info_->strict_mode() == SLOPPY &&
!info_->is_native()) {
Label ok;
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
@@ -269,6 +269,13 @@
}
+void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
+ if (!instr->IsLazyBailout() && !instr->IsGap()) {
+ safepoints_.BumpLastLazySafepointIndex();
+ }
+}
+
+
bool LCodeGen::GenerateDeferredCode() {
ASSERT(is_generating());
if (deferred_.length() > 0) {
@@ -1163,8 +1170,7 @@
// Check for negative zero.
HMod* hmod = instr->hydrogen();
- if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hmod->left()->CanBeNegative()) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ b(ne, &remainder_not_zero);
__ cmp(dividend, Operand::Zero());
@@ -1176,8 +1182,6 @@
void LCodeGen::DoModI(LModI* instr) {
HMod* hmod = instr->hydrogen();
- HValue* left = hmod->left();
- HValue* right = hmod->right();
if (CpuFeatures::IsSupported(SUDIV)) {
CpuFeatureScope scope(masm(), SUDIV);
@@ -1188,14 +1192,14 @@
Label done;
// Check for x % 0, sdiv might signal an exception. We have to deopt in this
// case because we can't return a NaN.
- if (right->CanBeZero()) {
+ if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right_reg, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
// Check for kMinInt % -1, sdiv will return kMinInt, which is not what we
// want. We have to deopt if we care about -0, because we can't return that.
- if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
+ if (hmod->CheckFlag(HValue::kCanOverflow)) {
Label no_overflow_possible;
__ cmp(left_reg, Operand(kMinInt));
__ b(ne, &no_overflow_possible);
@@ -1218,9 +1222,7 @@
__ mls(result_reg, result_reg, right_reg, left_reg);
// If we care about -0, test if the dividend is <0 and the result is 0.
- if (left->CanBeNegative() &&
- hmod->CanBeZero() &&
- hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ cmp(result_reg, Operand::Zero());
__ b(ne, &done);
__ cmp(left_reg, Operand::Zero());
@@ -1247,7 +1249,7 @@
Label done;
// Check for x % 0, we have to deopt in this case because we can't return a
// NaN.
- if (right->CanBeZero()) {
+ if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right_reg, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
@@ -1276,9 +1278,7 @@
__ sub(result_reg, left_reg, scratch, SetCC);
// If we care about -0, test if the dividend is <0 and the result is 0.
- if (left->CanBeNegative() &&
- hmod->CanBeZero() &&
- hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ b(ne, &done);
__ cmp(left_reg, Operand::Zero());
DeoptimizeIf(mi, instr->environment());
@@ -1297,14 +1297,12 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
// Check for (kMinInt / -1).
- if (hdiv->CheckFlag(HValue::kCanOverflow) &&
- hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) {
+ if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmp(dividend, Operand(kMinInt));
DeoptimizeIf(eq, instr->environment());
}
@@ -1347,8 +1345,7 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
@@ -1367,18 +1364,19 @@
void LCodeGen::DoDivI(LDivI* instr) {
+ HBinaryOperation* hdiv = instr->hydrogen();
const Register left = ToRegister(instr->left());
const Register right = ToRegister(instr->right());
const Register result = ToRegister(instr->result());
// Check for x / 0.
- if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
+ if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ cmp(right, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
// Check for (0 / -x) that will produce negative zero.
- if (instr->hydrogen_value()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label positive;
if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
// Do the test only if it hadn't be done above.
@@ -1391,10 +1389,9 @@
}
// Check for (kMinInt / -1).
- if (instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow) &&
+ if (hdiv->CheckFlag(HValue::kCanOverflow) &&
(!CpuFeatures::IsSupported(SUDIV) ||
- !instr->hydrogen_value()->CheckFlag(
- HValue::kAllUsesTruncatingToInt32))) {
+ !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
// We don't need to check for overflow when truncating with sdiv
// support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
__ cmp(left, Operand(kMinInt));
@@ -1406,8 +1403,7 @@
CpuFeatureScope scope(masm(), SUDIV);
__ sdiv(result, left, right);
- if (!instr->hydrogen_value()->CheckFlag(
- HInstruction::kAllUsesTruncatingToInt32)) {
+ if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Compute remainder and deopt if it's not zero.
const Register remainder = scratch0();
__ mls(remainder, result, right, left);
@@ -1425,8 +1421,7 @@
__ vcvt_s32_f64(double_scratch0().low(), vleft);
__ vmov(result, double_scratch0().low());
- if (!instr->hydrogen_value()->CheckFlag(
- HInstruction::kAllUsesTruncatingToInt32)) {
+ if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deopt if exact conversion to integer was not possible.
// Use vright as scratch register.
__ vcvt_f64_s32(double_scratch0(), double_scratch0().low());
@@ -1511,8 +1506,7 @@
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ cmp(dividend, Operand::Zero());
DeoptimizeIf(eq, instr->environment());
}
@@ -2079,7 +2073,6 @@
// is in the correct position.
Assembler::BlockConstPoolScope block_const_pool(masm());
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
- __ nop(); // Signals no inlined code.
}
@@ -3175,7 +3168,7 @@
case FAST_ELEMENTS:
case FAST_SMI_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4097,8 +4090,7 @@
// Name is always in r2.
__ mov(r2, Operand(instr->name()));
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag());
+ Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
}
@@ -4219,7 +4211,7 @@
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4335,7 +4327,7 @@
ASSERT(ToRegister(instr->key()).is(r1));
ASSERT(ToRegister(instr->value()).is(r0));
- Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+ Handle<Code> ic = instr->strict_mode() == STRICT
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
@@ -5373,7 +5365,7 @@
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(instr->hydrogen()->language_mode(),
+ FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
instr->hydrogen()->is_generator());
__ mov(r2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h
index e0f5009..21da500 100644
--- a/src/arm/lithium-codegen-arm.h
+++ b/src/arm/lithium-codegen-arm.h
@@ -164,9 +164,7 @@
#undef DECLARE_DO
private:
- StrictModeFlag strict_mode_flag() const {
- return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
- }
+ StrictMode strict_mode() const { return info()->strict_mode(); }
Scope* scope() const { return scope_; }
@@ -193,6 +191,7 @@
// Code generation passes. Returns true if code generation should
// continue.
+ void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE;
bool GeneratePrologue();
bool GenerateDeferredCode();
bool GenerateDeoptJumpTable();
diff --git a/src/array.js b/src/array.js
index 372b7ec..9b71283 100644
--- a/src/array.js
+++ b/src/array.js
@@ -1153,7 +1153,7 @@
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(f) || receiver;
- } else if (!IS_SPEC_OBJECT(receiver) && %IsClassicModeFunction(f)) {
+ } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
receiver = ToObject(receiver);
}
@@ -1201,7 +1201,7 @@
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(f) || receiver;
- } else if (!IS_SPEC_OBJECT(receiver) && %IsClassicModeFunction(f)) {
+ } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
receiver = ToObject(receiver);
}
@@ -1242,7 +1242,7 @@
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(f) || receiver;
- } else if (!IS_SPEC_OBJECT(receiver) && %IsClassicModeFunction(f)) {
+ } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
receiver = ToObject(receiver);
}
@@ -1282,7 +1282,7 @@
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(f) || receiver;
- } else if (!IS_SPEC_OBJECT(receiver) && %IsClassicModeFunction(f)) {
+ } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
receiver = ToObject(receiver);
}
@@ -1321,7 +1321,7 @@
}
if (IS_NULL_OR_UNDEFINED(receiver)) {
receiver = %GetDefaultReceiver(f) || receiver;
- } else if (!IS_SPEC_OBJECT(receiver) && %IsClassicModeFunction(f)) {
+ } else if (!IS_SPEC_OBJECT(receiver) && %IsSloppyModeFunction(f)) {
receiver = ToObject(receiver);
}
diff --git a/src/ast.cc b/src/ast.cc
index 6b2f48f..997d3e0 100644
--- a/src/ast.cc
+++ b/src/ast.cc
@@ -180,8 +180,8 @@
}
-LanguageMode FunctionLiteral::language_mode() const {
- return scope()->language_mode();
+StrictMode FunctionLiteral::strict_mode() const {
+ return scope()->strict_mode();
}
@@ -379,9 +379,9 @@
} else if (boilerplate_value->IsUninitialized()) {
is_simple = false;
JSObject::SetOwnElement(
- array, i, handle(Smi::FromInt(0), isolate), kNonStrictMode);
+ array, i, handle(Smi::FromInt(0), isolate), SLOPPY);
} else {
- JSObject::SetOwnElement(array, i, boilerplate_value, kNonStrictMode);
+ JSObject::SetOwnElement(array, i, boilerplate_value, SLOPPY);
}
}
diff --git a/src/ast.h b/src/ast.h
index aacc5e4..262b41a 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -2315,8 +2315,7 @@
int SourceSize() const { return end_position() - start_position(); }
bool is_expression() const { return IsExpression::decode(bitfield_); }
bool is_anonymous() const { return IsAnonymous::decode(bitfield_); }
- bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
- LanguageMode language_mode() const;
+ StrictMode strict_mode() const;
int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; }
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 61361f8..dd2ddad 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -300,7 +300,7 @@
PrototypePropertyMode prototypeMode);
void MakeFunctionInstancePrototypeWritable();
- Handle<Map> CreateStrictModeFunctionMap(
+ Handle<Map> CreateStrictFunctionMap(
PrototypePropertyMode prototype_mode,
Handle<JSFunction> empty_function);
@@ -328,8 +328,8 @@
// prototype for the processing of JS builtins. Later the function maps are
// replaced in order to make prototype writable. These are the final, writable
// prototype, maps.
- Handle<Map> function_map_writable_prototype_;
- Handle<Map> strict_mode_function_map_writable_prototype_;
+ Handle<Map> sloppy_function_map_writable_prototype_;
+ Handle<Map> strict_function_map_writable_prototype_;
Handle<JSFunction> throw_type_error_function;
BootstrapperActive active_;
@@ -474,18 +474,19 @@
// can not be used as constructors.
Handle<Map> function_without_prototype_map =
CreateFunctionMap(DONT_ADD_PROTOTYPE);
- native_context()->set_function_without_prototype_map(
+ native_context()->set_sloppy_function_without_prototype_map(
*function_without_prototype_map);
// Allocate the function map. This map is temporary, used only for processing
// of builtins.
// Later the map is replaced with writable prototype map, allocated below.
Handle<Map> function_map = CreateFunctionMap(ADD_READONLY_PROTOTYPE);
- native_context()->set_function_map(*function_map);
+ native_context()->set_sloppy_function_map(*function_map);
// The final map for functions. Writeable prototype.
// This map is installed in MakeFunctionInstancePrototypeWritable.
- function_map_writable_prototype_ = CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE);
+ sloppy_function_map_writable_prototype_ =
+ CreateFunctionMap(ADD_WRITEABLE_PROTOTYPE);
Factory* factory = isolate->factory();
@@ -519,7 +520,7 @@
Handle<String> empty_string =
factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("Empty"));
Handle<JSFunction> empty_function =
- factory->NewFunctionWithoutPrototype(empty_string, CLASSIC_MODE);
+ factory->NewFunctionWithoutPrototype(empty_string, SLOPPY);
// --- E m p t y ---
Handle<Code> code =
@@ -537,10 +538,10 @@
empty_function->shared()->DontAdaptArguments();
// Set prototypes for the function maps.
- native_context()->function_map()->set_prototype(*empty_function);
- native_context()->function_without_prototype_map()->
+ native_context()->sloppy_function_map()->set_prototype(*empty_function);
+ native_context()->sloppy_function_without_prototype_map()->
set_prototype(*empty_function);
- function_map_writable_prototype_->set_prototype(*empty_function);
+ sloppy_function_map_writable_prototype_->set_prototype(*empty_function);
// Allocate the function map first and then patch the prototype later
Handle<Map> empty_function_map = CreateFunctionMap(DONT_ADD_PROTOTYPE);
@@ -604,11 +605,10 @@
Handle<String> name = factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("ThrowTypeError"));
throw_type_error_function =
- factory()->NewFunctionWithoutPrototype(name, CLASSIC_MODE);
+ factory()->NewFunctionWithoutPrototype(name, SLOPPY);
Handle<Code> code(isolate()->builtins()->builtin(
Builtins::kStrictModePoisonPill));
- throw_type_error_function->set_map(
- native_context()->function_map());
+ throw_type_error_function->set_map(native_context()->sloppy_function_map());
throw_type_error_function->set_code(*code);
throw_type_error_function->shared()->set_code(*code);
throw_type_error_function->shared()->DontAdaptArguments();
@@ -619,7 +619,7 @@
}
-Handle<Map> Genesis::CreateStrictModeFunctionMap(
+Handle<Map> Genesis::CreateStrictFunctionMap(
PrototypePropertyMode prototype_mode,
Handle<JSFunction> empty_function) {
Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
@@ -632,28 +632,27 @@
void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) {
// Allocate map for the prototype-less strict mode instances.
- Handle<Map> strict_mode_function_without_prototype_map =
- CreateStrictModeFunctionMap(DONT_ADD_PROTOTYPE, empty);
- native_context()->set_strict_mode_function_without_prototype_map(
- *strict_mode_function_without_prototype_map);
+ Handle<Map> strict_function_without_prototype_map =
+ CreateStrictFunctionMap(DONT_ADD_PROTOTYPE, empty);
+ native_context()->set_strict_function_without_prototype_map(
+ *strict_function_without_prototype_map);
// Allocate map for the strict mode functions. This map is temporary, used
// only for processing of builtins.
// Later the map is replaced with writable prototype map, allocated below.
- Handle<Map> strict_mode_function_map =
- CreateStrictModeFunctionMap(ADD_READONLY_PROTOTYPE, empty);
- native_context()->set_strict_mode_function_map(
- *strict_mode_function_map);
+ Handle<Map> strict_function_map =
+ CreateStrictFunctionMap(ADD_READONLY_PROTOTYPE, empty);
+ native_context()->set_strict_function_map(*strict_function_map);
// The final map for the strict mode functions. Writeable prototype.
// This map is installed in MakeFunctionInstancePrototypeWritable.
- strict_mode_function_map_writable_prototype_ =
- CreateStrictModeFunctionMap(ADD_WRITEABLE_PROTOTYPE, empty);
+ strict_function_map_writable_prototype_ =
+ CreateStrictFunctionMap(ADD_WRITEABLE_PROTOTYPE, empty);
// Complete the callbacks.
- PoisonArgumentsAndCaller(strict_mode_function_without_prototype_map);
- PoisonArgumentsAndCaller(strict_mode_function_map);
- PoisonArgumentsAndCaller(strict_mode_function_map_writable_prototype_);
+ PoisonArgumentsAndCaller(strict_function_without_prototype_map);
+ PoisonArgumentsAndCaller(strict_function_map);
+ PoisonArgumentsAndCaller(strict_function_map_writable_prototype_);
}
@@ -1137,7 +1136,7 @@
function->shared()->set_expected_nof_properties(2);
Handle<JSObject> result = factory->NewJSObject(function);
- native_context()->set_arguments_boilerplate(*result);
+ native_context()->set_sloppy_arguments_boilerplate(*result);
// Note: length must be added as the first property and
// callee must be added as the second property.
CHECK_NOT_EMPTY_HANDLE(isolate,
@@ -1173,22 +1172,23 @@
{ // --- aliased_arguments_boilerplate_
// Set up a well-formed parameter map to make assertions happy.
Handle<FixedArray> elements = factory->NewFixedArray(2);
- elements->set_map(heap->non_strict_arguments_elements_map());
+ elements->set_map(heap->sloppy_arguments_elements_map());
Handle<FixedArray> array;
array = factory->NewFixedArray(0);
elements->set(0, *array);
array = factory->NewFixedArray(0);
elements->set(1, *array);
- Handle<Map> old_map(native_context()->arguments_boilerplate()->map());
+ Handle<Map> old_map(
+ native_context()->sloppy_arguments_boilerplate()->map());
Handle<Map> new_map = factory->CopyMap(old_map);
new_map->set_pre_allocated_property_fields(2);
Handle<JSObject> result = factory->NewJSObjectFromMap(new_map);
// Set elements kind after allocating the object because
// NewJSObjectFromMap assumes a fast elements map.
- new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
+ new_map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
result->set_elements(*elements);
- ASSERT(result->HasNonStrictArgumentsElements());
+ ASSERT(result->HasSloppyArgumentsElements());
native_context()->set_aliased_arguments_boilerplate(*result);
}
@@ -1211,7 +1211,7 @@
// Create the map. Allocate one in-object field for length.
Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE,
- Heap::kArgumentsObjectSizeStrict);
+ Heap::kStrictArgumentsObjectSize);
// Create the descriptor array for the arguments object.
Handle<DescriptorArray> descriptors = factory->NewDescriptorArray(0, 3);
DescriptorArray::WhitenessWitness witness(*descriptors);
@@ -1240,13 +1240,13 @@
map->set_pre_allocated_property_fields(1);
map->set_inobject_properties(1);
- // Copy constructor from the non-strict arguments boilerplate.
+ // Copy constructor from the sloppy arguments boilerplate.
map->set_constructor(
- native_context()->arguments_boilerplate()->map()->constructor());
+ native_context()->sloppy_arguments_boilerplate()->map()->constructor());
// Allocate the arguments boilerplate object.
Handle<JSObject> result = factory->NewJSObjectFromMap(map);
- native_context()->set_strict_mode_arguments_boilerplate(*result);
+ native_context()->set_strict_arguments_boilerplate(*result);
// Add length property only for strict mode boilerplate.
CHECK_NOT_EMPTY_HANDLE(isolate,
@@ -1389,18 +1389,19 @@
// Create maps for generator functions and their prototypes. Store those
// maps in the native context.
- Handle<Map> function_map(native_context()->function_map());
+ Handle<Map> function_map(native_context()->sloppy_function_map());
Handle<Map> generator_function_map = factory()->CopyMap(function_map);
generator_function_map->set_prototype(*generator_function_prototype);
- native_context()->set_generator_function_map(*generator_function_map);
+ native_context()->set_sloppy_generator_function_map(
+ *generator_function_map);
Handle<Map> strict_mode_function_map(
- native_context()->strict_mode_function_map());
+ native_context()->strict_function_map());
Handle<Map> strict_mode_generator_function_map = factory()->CopyMap(
strict_mode_function_map);
strict_mode_generator_function_map->set_prototype(
*generator_function_prototype);
- native_context()->set_strict_mode_generator_function_map(
+ native_context()->set_strict_generator_function_map(
*strict_mode_generator_function_map);
Handle<Map> object_map(native_context()->object_function()->initial_map());
@@ -1585,6 +1586,15 @@
INSTALL_NATIVE(JSFunction, "EnqueueExternalMicrotask",
enqueue_external_microtask);
+ if (FLAG_harmony_promises) {
+ INSTALL_NATIVE(JSFunction, "IsPromise", is_promise);
+ INSTALL_NATIVE(JSFunction, "PromiseCreate", promise_create);
+ INSTALL_NATIVE(JSFunction, "PromiseResolve", promise_resolve);
+ INSTALL_NATIVE(JSFunction, "PromiseReject", promise_reject);
+ INSTALL_NATIVE(JSFunction, "PromiseChain", promise_chain);
+ INSTALL_NATIVE(JSFunction, "PromiseCatch", promise_catch);
+ }
+
if (FLAG_harmony_proxies) {
INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap);
INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap);
@@ -2550,13 +2560,14 @@
// The maps with writable prototype are created in CreateEmptyFunction
// and CreateStrictModeFunctionMaps respectively. Initially the maps are
// created with read-only prototype for JS builtins processing.
- ASSERT(!function_map_writable_prototype_.is_null());
- ASSERT(!strict_mode_function_map_writable_prototype_.is_null());
+ ASSERT(!sloppy_function_map_writable_prototype_.is_null());
+ ASSERT(!strict_function_map_writable_prototype_.is_null());
// Replace function instance maps to make prototype writable.
- native_context()->set_function_map(*function_map_writable_prototype_);
- native_context()->set_strict_mode_function_map(
- *strict_mode_function_map_writable_prototype_);
+ native_context()->set_sloppy_function_map(
+ *sloppy_function_map_writable_prototype_);
+ native_context()->set_strict_function_map(
+ *strict_function_map_writable_prototype_);
}
diff --git a/src/builtins.cc b/src/builtins.cc
index f6b21f2..4e5fbd3 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -677,8 +677,8 @@
} else {
// Array.slice(arguments, ...) is quite a common idiom (notably more
// than 50% of invocations in Web apps). Treat it in C++ as well.
- Map* arguments_map =
- isolate->context()->native_context()->arguments_boilerplate()->map();
+ Map* arguments_map = isolate->context()->native_context()->
+ sloppy_arguments_boilerplate()->map();
bool is_arguments_object_with_fast_elements =
receiver->IsJSObject() &&
@@ -1174,7 +1174,7 @@
}
SharedFunctionInfo* shared = function->shared();
- if (shared->is_classic_mode() && !shared->native()) {
+ if (shared->strict_mode() == SLOPPY && !shared->native()) {
Object* recv = args[0];
ASSERT(!recv->IsNull());
if (recv->IsUndefined()) {
@@ -1364,8 +1364,8 @@
}
-static void Generate_KeyedLoadIC_NonStrictArguments(MacroAssembler* masm) {
- KeyedLoadIC::GenerateNonStrictArguments(masm);
+static void Generate_KeyedLoadIC_SloppyArguments(MacroAssembler* masm) {
+ KeyedLoadIC::GenerateSloppyArguments(masm);
}
@@ -1390,12 +1390,12 @@
static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode);
+ KeyedStoreIC::GenerateGeneric(masm, SLOPPY);
}
static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
- KeyedStoreIC::GenerateGeneric(masm, kStrictMode);
+ KeyedStoreIC::GenerateGeneric(masm, STRICT);
}
@@ -1429,8 +1429,8 @@
}
-static void Generate_KeyedStoreIC_NonStrictArguments(MacroAssembler* masm) {
- KeyedStoreIC::GenerateNonStrictArguments(masm);
+static void Generate_KeyedStoreIC_SloppyArguments(MacroAssembler* masm) {
+ KeyedStoreIC::GenerateSloppyArguments(masm);
}
diff --git a/src/builtins.h b/src/builtins.h
index d977a48..88cfd53 100644
--- a/src/builtins.h
+++ b/src/builtins.h
@@ -137,7 +137,7 @@
kNoExtraICState) \
V(KeyedLoadIC_IndexedInterceptor, KEYED_LOAD_IC, MONOMORPHIC, \
kNoExtraICState) \
- V(KeyedLoadIC_NonStrictArguments, KEYED_LOAD_IC, MONOMORPHIC, \
+ V(KeyedLoadIC_SloppyArguments, KEYED_LOAD_IC, MONOMORPHIC, \
kNoExtraICState) \
\
V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, \
@@ -156,8 +156,8 @@
StoreIC::kStrictModeState) \
V(KeyedStoreIC_Generic_Strict, KEYED_STORE_IC, GENERIC, \
StoreIC::kStrictModeState) \
- V(KeyedStoreIC_NonStrictArguments, KEYED_STORE_IC, MONOMORPHIC, \
- kNoExtraICState) \
+ V(KeyedStoreIC_SloppyArguments, KEYED_STORE_IC, MONOMORPHIC, \
+ kNoExtraICState) \
\
/* Uses KeyedLoadIC_Initialize; must be after in list. */ \
V(FunctionCall, BUILTIN, UNINITIALIZED, \
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index 7bd5d8b..23095f7 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -1293,7 +1293,7 @@
HInstruction* js_function = Add<HAllocate>(size, HType::JSObject(),
NOT_TENURED, JS_FUNCTION_TYPE);
- int map_index = Context::FunctionMapIndex(casted_stub()->language_mode(),
+ int map_index = Context::FunctionMapIndex(casted_stub()->strict_mode(),
casted_stub()->is_generator());
// Compute the function map in the current native context and set that
diff --git a/src/code-stubs.cc b/src/code-stubs.cc
index fe7d77e..6bf0479 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -561,7 +561,7 @@
case DICTIONARY_ELEMENTS:
KeyedStoreStubCompiler::GenerateStoreDictionaryElement(masm);
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -572,8 +572,8 @@
stream->Add("ArgumentsAccessStub_");
switch (type_) {
case READ_ELEMENT: stream->Add("ReadElement"); break;
- case NEW_NON_STRICT_FAST: stream->Add("NewNonStrictFast"); break;
- case NEW_NON_STRICT_SLOW: stream->Add("NewNonStrictSlow"); break;
+ case NEW_SLOPPY_FAST: stream->Add("NewSloppyFast"); break;
+ case NEW_SLOPPY_SLOW: stream->Add("NewSloppySlow"); break;
case NEW_STRICT: stream->Add("NewStrict"); break;
}
}
@@ -736,7 +736,7 @@
void FastNewClosureStub::InstallDescriptors(Isolate* isolate) {
- FastNewClosureStub stub(STRICT_MODE, false);
+ FastNewClosureStub stub(STRICT, false);
InstallDescriptor(isolate, &stub);
}
diff --git a/src/code-stubs.h b/src/code-stubs.h
index 62026a8..c86b3a4 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -522,8 +522,8 @@
class FastNewClosureStub : public HydrogenCodeStub {
public:
- explicit FastNewClosureStub(LanguageMode language_mode, bool is_generator)
- : language_mode_(language_mode),
+ explicit FastNewClosureStub(StrictMode strict_mode, bool is_generator)
+ : strict_mode_(strict_mode),
is_generator_(is_generator) { }
virtual Handle<Code> GenerateCode(Isolate* isolate);
@@ -534,7 +534,7 @@
static void InstallDescriptors(Isolate* isolate);
- LanguageMode language_mode() const { return language_mode_; }
+ StrictMode strict_mode() const { return strict_mode_; }
bool is_generator() const { return is_generator_; }
private:
@@ -543,11 +543,11 @@
Major MajorKey() { return FastNewClosure; }
int NotMissMinorKey() {
- return StrictModeBits::encode(language_mode_ != CLASSIC_MODE) |
+ return StrictModeBits::encode(strict_mode_ == STRICT) |
IsGeneratorBits::encode(is_generator_);
}
- LanguageMode language_mode_;
+ StrictMode strict_mode_;
bool is_generator_;
};
@@ -659,8 +659,7 @@
// Maximum number of properties in copied object.
static const int kMaximumClonedProperties = 6;
- explicit FastCloneShallowObjectStub(int length)
- : length_(length) {
+ explicit FastCloneShallowObjectStub(int length) : length_(length) {
ASSERT_GE(length_, 0);
ASSERT_LE(length_, kMaximumClonedProperties);
}
@@ -847,7 +846,7 @@
class StoreICStub: public ICStub {
public:
- StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
+ StoreICStub(Code::Kind kind, StrictMode strict_mode)
: ICStub(kind), strict_mode_(strict_mode) { }
protected:
@@ -862,13 +861,13 @@
return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
}
- StrictModeFlag strict_mode_;
+ StrictMode strict_mode_;
};
class StoreArrayLengthStub: public StoreICStub {
public:
- explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
+ explicit StoreArrayLengthStub(Code::Kind kind, StrictMode strict_mode)
: StoreICStub(kind, strict_mode) { }
virtual void Generate(MacroAssembler* masm);
@@ -1535,8 +1534,8 @@
public:
enum Type {
READ_ELEMENT,
- NEW_NON_STRICT_FAST,
- NEW_NON_STRICT_SLOW,
+ NEW_SLOPPY_FAST,
+ NEW_SLOPPY_SLOW,
NEW_STRICT
};
@@ -1551,8 +1550,8 @@
void Generate(MacroAssembler* masm);
void GenerateReadElement(MacroAssembler* masm);
void GenerateNewStrict(MacroAssembler* masm);
- void GenerateNewNonStrictFast(MacroAssembler* masm);
- void GenerateNewNonStrictSlow(MacroAssembler* masm);
+ void GenerateNewSloppyFast(MacroAssembler* masm);
+ void GenerateNewSloppySlow(MacroAssembler* masm);
virtual void PrintName(StringStream* stream);
};
diff --git a/src/codegen.cc b/src/codegen.cc
index f6c3668..ea0ead3 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -222,11 +222,11 @@
case READ_ELEMENT:
GenerateReadElement(masm);
break;
- case NEW_NON_STRICT_FAST:
- GenerateNewNonStrictFast(masm);
+ case NEW_SLOPPY_FAST:
+ GenerateNewSloppyFast(masm);
break;
- case NEW_NON_STRICT_SLOW:
- GenerateNewNonStrictSlow(masm);
+ case NEW_SLOPPY_SLOW:
+ GenerateNewSloppySlow(masm);
break;
case NEW_STRICT:
GenerateNewStrict(masm);
diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc
index a69ef4c..54d4565 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -269,7 +269,7 @@
Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
Handle<String> source,
Handle<Context> context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position) {
// Make sure not to leak the table into the surrounding handle
// scope. Otherwise, we risk keeping old tables around even after
@@ -280,7 +280,7 @@
for (generation = 0; generation < generations(); generation++) {
Handle<CompilationCacheTable> table = GetTable(generation);
result = table->LookupEval(
- *source, *context, language_mode, scope_position);
+ *source, *context, strict_mode, scope_position);
if (result->IsSharedFunctionInfo()) {
break;
}
@@ -421,7 +421,7 @@
Handle<SharedFunctionInfo> CompilationCache::LookupEval(
Handle<String> source,
Handle<Context> context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position) {
if (!IsEnabled()) {
return Handle<SharedFunctionInfo>::null();
@@ -430,11 +430,11 @@
Handle<SharedFunctionInfo> result;
if (context->IsNativeContext()) {
result = eval_global_.Lookup(
- source, context, language_mode, scope_position);
+ source, context, strict_mode, scope_position);
} else {
ASSERT(scope_position != RelocInfo::kNoPosition);
result = eval_contextual_.Lookup(
- source, context, language_mode, scope_position);
+ source, context, strict_mode, scope_position);
}
return result;
}
diff --git a/src/compilation-cache.h b/src/compilation-cache.h
index ead52b5..b31de31 100644
--- a/src/compilation-cache.h
+++ b/src/compilation-cache.h
@@ -136,10 +136,9 @@
// entries:
// 1. The source string.
// 2. The shared function info of the calling function.
-// 3. Whether the source should be compiled as strict code or as non-strict
-// code.
+// 3. Whether the source should be compiled as strict code or as sloppy code.
// Note: Currently there are clients of CompileEval that always compile
-// non-strict code even if the calling function is a strict mode function.
+// sloppy code even if the calling function is a strict mode function.
// More specifically these are the CompileString, DebugEvaluate and
// DebugEvaluateGlobal runtime functions.
// 4. The start position of the calling scope.
@@ -150,7 +149,7 @@
Handle<SharedFunctionInfo> Lookup(Handle<String> source,
Handle<Context> context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position);
void Put(Handle<String> source,
@@ -222,7 +221,7 @@
// contain a script for the given source string.
Handle<SharedFunctionInfo> LookupEval(Handle<String> source,
Handle<Context> context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position);
// Returns the regexp data associated with the given regexp if it
diff --git a/src/compiler.cc b/src/compiler.cc
index 89864e0..21f107a 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -56,7 +56,7 @@
CompilationInfo::CompilationInfo(Handle<Script> script,
Zone* zone)
- : flags_(LanguageModeField::encode(CLASSIC_MODE)),
+ : flags_(StrictModeField::encode(SLOPPY)),
script_(script),
osr_ast_id_(BailoutId::None()),
parameter_count_(0),
@@ -68,7 +68,7 @@
CompilationInfo::CompilationInfo(Handle<SharedFunctionInfo> shared_info,
Zone* zone)
- : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
+ : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)),
shared_info_(shared_info),
script_(Handle<Script>(Script::cast(shared_info->script()))),
osr_ast_id_(BailoutId::None()),
@@ -81,7 +81,7 @@
CompilationInfo::CompilationInfo(Handle<JSFunction> closure,
Zone* zone)
- : flags_(LanguageModeField::encode(CLASSIC_MODE) | IsLazy::encode(true)),
+ : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)),
closure_(closure),
shared_info_(Handle<SharedFunctionInfo>(closure->shared())),
script_(Handle<Script>(Script::cast(shared_info_->script()))),
@@ -97,8 +97,7 @@
CompilationInfo::CompilationInfo(HydrogenCodeStub* stub,
Isolate* isolate,
Zone* zone)
- : flags_(LanguageModeField::encode(CLASSIC_MODE) |
- IsLazy::encode(true)),
+ : flags_(StrictModeField::encode(SLOPPY) | IsLazy::encode(true)),
osr_ast_id_(BailoutId::None()),
parameter_count_(0),
this_has_uses_(true),
@@ -137,8 +136,8 @@
MarkAsNative();
}
if (!shared_info_.is_null()) {
- ASSERT(language_mode() == CLASSIC_MODE);
- SetLanguageMode(shared_info_->language_mode());
+ ASSERT(strict_mode() == SLOPPY);
+ SetStrictMode(shared_info_->strict_mode());
}
set_bailout_reason(kUnknown);
@@ -237,7 +236,7 @@
FLAG_optimize_closures &&
closure_.is_null() &&
!scope_->HasTrivialOuterContext() &&
- !scope_->outer_scope_calls_non_strict_eval() &&
+ !scope_->outer_scope_calls_sloppy_eval() &&
!scope_->inside_with();
SetMode(is_optimizable_closure ? BASE : NONOPT);
}
@@ -606,7 +605,7 @@
shared->set_dont_optimize_reason(lit->dont_optimize_reason());
shared->set_dont_inline(lit->flags()->Contains(kDontInline));
shared->set_ast_node_count(lit->ast_node_count());
- shared->set_language_mode(lit->language_mode());
+ shared->set_strict_mode(lit->strict_mode());
}
@@ -631,7 +630,7 @@
function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
function_info->set_allows_lazy_compilation_without_context(
lit->AllowsLazyCompilationWithoutContext());
- function_info->set_language_mode(lit->language_mode());
+ function_info->set_strict_mode(lit->strict_mode());
function_info->set_uses_arguments(lit->scope()->arguments() != NULL);
function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
function_info->set_ast_node_count(lit->ast_node_count());
@@ -662,8 +661,7 @@
VMState<COMPILER> state(info->isolate());
PostponeInterruptsScope postpone(info->isolate());
if (!Parser::Parse(info)) return Handle<Code>::null();
- LanguageMode language_mode = info->function()->language_mode();
- info->SetLanguageMode(language_mode);
+ info->SetStrictMode(info->function()->strict_mode());
if (!CompileUnoptimizedCode(info)) return Handle<Code>::null();
Compiler::RecordFunctionCompilation(
@@ -771,8 +769,7 @@
info.MarkAsGlobal();
if (!Parser::Parse(&info)) return;
- LanguageMode language_mode = info.function()->language_mode();
- info.SetLanguageMode(language_mode);
+ info.SetStrictMode(info.function()->strict_mode());
LiveEditFunctionTracker tracker(info.isolate(), info.function());
if (!CompileUnoptimizedCode(&info)) return;
@@ -889,7 +886,7 @@
Handle<JSFunction> Compiler::GetFunctionFromEval(Handle<String> source,
Handle<Context> context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
ParseRestriction restriction,
int scope_position) {
Isolate* isolate = source->GetIsolate();
@@ -899,14 +896,14 @@
CompilationCache* compilation_cache = isolate->compilation_cache();
Handle<SharedFunctionInfo> shared_info = compilation_cache->LookupEval(
- source, context, language_mode, scope_position);
+ source, context, strict_mode, scope_position);
if (shared_info.is_null()) {
Handle<Script> script = isolate->factory()->NewScript(source);
CompilationInfoWithZone info(script);
info.MarkAsEval();
if (context->IsNativeContext()) info.MarkAsGlobal();
- info.SetLanguageMode(language_mode);
+ info.SetStrictMode(strict_mode);
info.SetParseRestriction(restriction);
info.SetContext(context);
@@ -923,14 +920,8 @@
// to handle eval-code in the optimizing compiler.
shared_info->DisableOptimization(kEval);
- // If caller is strict mode, the result must be in strict mode or
- // extended mode as well, but not the other way around. Consider:
- // eval("'use strict'; ...");
- ASSERT(language_mode != STRICT_MODE || !shared_info->is_classic_mode());
- // If caller is in extended mode, the result must also be in
- // extended mode.
- ASSERT(language_mode != EXTENDED_MODE ||
- shared_info->is_extended_mode());
+ // If caller is strict mode, the result must be in strict mode as well.
+ ASSERT(strict_mode == SLOPPY || shared_info->strict_mode() == STRICT);
if (!shared_info->dont_cache()) {
compilation_cache->PutEval(
source, context, shared_info, scope_position);
@@ -1000,9 +991,7 @@
info.SetExtension(extension);
info.SetPreParseData(pre_data);
info.SetContext(context);
- if (FLAG_use_strict) {
- info.SetLanguageMode(FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE);
- }
+ if (FLAG_use_strict) info.SetStrictMode(STRICT);
result = CompileToplevel(&info);
if (extension == NULL && !result.is_null() && !result->dont_cache()) {
compilation_cache->PutScript(source, context, result);
@@ -1022,7 +1011,7 @@
CompilationInfoWithZone info(script);
info.SetFunction(literal);
info.PrepareForCompilation(literal->scope());
- info.SetLanguageMode(literal->scope()->language_mode());
+ info.SetStrictMode(literal->scope()->strict_mode());
Isolate* isolate = info.isolate();
Factory* factory = isolate->factory();
@@ -1118,8 +1107,7 @@
static bool CompileOptimizedPrologue(CompilationInfo* info) {
if (!Parser::Parse(info)) return false;
- LanguageMode language_mode = info->function()->language_mode();
- info->SetLanguageMode(language_mode);
+ info->SetStrictMode(info->function()->strict_mode());
if (!Rewriter::Rewrite(info)) return false;
if (!Scope::Analyze(info)) return false;
diff --git a/src/compiler.h b/src/compiler.h
index 2f83043..e4ade7b 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -66,11 +66,7 @@
bool is_lazy() const { return IsLazy::decode(flags_); }
bool is_eval() const { return IsEval::decode(flags_); }
bool is_global() const { return IsGlobal::decode(flags_); }
- bool is_classic_mode() const { return language_mode() == CLASSIC_MODE; }
- bool is_extended_mode() const { return language_mode() == EXTENDED_MODE; }
- LanguageMode language_mode() const {
- return LanguageModeField::decode(flags_);
- }
+ StrictMode strict_mode() const { return StrictModeField::decode(flags_); }
bool is_in_loop() const { return IsInLoop::decode(flags_); }
FunctionLiteral* function() const { return function_; }
Scope* scope() const { return scope_; }
@@ -109,11 +105,9 @@
bool this_has_uses() {
return this_has_uses_;
}
- void SetLanguageMode(LanguageMode language_mode) {
- ASSERT(this->language_mode() == CLASSIC_MODE ||
- this->language_mode() == language_mode ||
- language_mode == EXTENDED_MODE);
- flags_ = LanguageModeField::update(flags_, language_mode);
+ void SetStrictMode(StrictMode strict_mode) {
+ ASSERT(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode);
+ flags_ = StrictModeField::update(flags_, strict_mode);
}
void MarkAsInLoop() {
ASSERT(is_lazy());
@@ -363,26 +357,26 @@
// Flags that can be set for lazy compilation.
class IsInLoop: public BitField<bool, 3, 1> {};
// Strict mode - used in eager compilation.
- class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
+ class StrictModeField: public BitField<StrictMode, 4, 1> {};
// Is this a function from our natives.
- class IsNative: public BitField<bool, 6, 1> {};
+ class IsNative: public BitField<bool, 5, 1> {};
// Is this code being compiled with support for deoptimization..
- class SupportsDeoptimization: public BitField<bool, 7, 1> {};
+ class SupportsDeoptimization: public BitField<bool, 6, 1> {};
// If compiling for debugging produce just full code matching the
// initial mode setting.
- class IsCompilingForDebugging: public BitField<bool, 8, 1> {};
+ class IsCompilingForDebugging: public BitField<bool, 7, 1> {};
// If the compiled code contains calls that require building a frame
- class IsCalling: public BitField<bool, 9, 1> {};
+ class IsCalling: public BitField<bool, 8, 1> {};
// If the compiled code contains calls that require building a frame
- class IsDeferredCalling: public BitField<bool, 10, 1> {};
+ class IsDeferredCalling: public BitField<bool, 9, 1> {};
// If the compiled code contains calls that require building a frame
- class IsNonDeferredCalling: public BitField<bool, 11, 1> {};
+ class IsNonDeferredCalling: public BitField<bool, 10, 1> {};
// If the compiled code saves double caller registers that it clobbers.
- class SavesCallerDoubles: public BitField<bool, 12, 1> {};
+ class SavesCallerDoubles: public BitField<bool, 11, 1> {};
// If the set of valid statements is restricted.
- class ParseRestricitonField: public BitField<ParseRestriction, 13, 1> {};
+ class ParseRestricitonField: public BitField<ParseRestriction, 12, 1> {};
// If the function requires a frame (for unspecified reasons)
- class RequiresFrame: public BitField<bool, 14, 1> {};
+ class RequiresFrame: public BitField<bool, 13, 1> {};
unsigned flags_;
@@ -624,7 +618,7 @@
// Compile a String source within a context for eval.
static Handle<JSFunction> GetFunctionFromEval(Handle<String> source,
Handle<Context> context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
ParseRestriction restriction,
int scope_position);
diff --git a/src/contexts.cc b/src/contexts.cc
index 710d30a..964347f 100644
--- a/src/contexts.cc
+++ b/src/contexts.cc
@@ -185,12 +185,12 @@
*binding_flags = (init_flag == kNeedsInitialization)
? MUTABLE_CHECK_INITIALIZED : MUTABLE_IS_INITIALIZED;
break;
- case CONST:
+ case CONST_LEGACY:
*attributes = READ_ONLY;
*binding_flags = (init_flag == kNeedsInitialization)
? IMMUTABLE_CHECK_INITIALIZED : IMMUTABLE_IS_INITIALIZED;
break;
- case CONST_HARMONY:
+ case CONST:
*attributes = READ_ONLY;
*binding_flags = (init_flag == kNeedsInitialization)
? IMMUTABLE_CHECK_INITIALIZED_HARMONY :
@@ -222,8 +222,8 @@
}
*index = function_index;
*attributes = READ_ONLY;
- ASSERT(mode == CONST || mode == CONST_HARMONY);
- *binding_flags = (mode == CONST)
+ ASSERT(mode == CONST_LEGACY || mode == CONST);
+ *binding_flags = (mode == CONST_LEGACY)
? IMMUTABLE_IS_INITIALIZED : IMMUTABLE_IS_INITIALIZED_HARMONY;
return context;
}
diff --git a/src/contexts.h b/src/contexts.h
index d15ef86..479a692 100644
--- a/src/contexts.h
+++ b/src/contexts.h
@@ -135,17 +135,19 @@
V(FLOAT64_ARRAY_FUN_INDEX, JSFunction, float64_array_fun) \
V(UINT8_CLAMPED_ARRAY_FUN_INDEX, JSFunction, uint8_clamped_array_fun) \
V(DATA_VIEW_FUN_INDEX, JSFunction, data_view_fun) \
- V(FUNCTION_MAP_INDEX, Map, function_map) \
- V(STRICT_MODE_FUNCTION_MAP_INDEX, Map, strict_mode_function_map) \
- V(FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, function_without_prototype_map) \
- V(STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
- strict_mode_function_without_prototype_map) \
+ V(SLOPPY_FUNCTION_MAP_INDEX, Map, sloppy_function_map) \
+ V(STRICT_FUNCTION_MAP_INDEX, Map, strict_function_map) \
+ V(SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
+ sloppy_function_without_prototype_map) \
+ V(STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX, Map, \
+ strict_function_without_prototype_map) \
V(REGEXP_RESULT_MAP_INDEX, Map, regexp_result_map)\
- V(ARGUMENTS_BOILERPLATE_INDEX, JSObject, arguments_boilerplate) \
+ V(SLOPPY_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
+ sloppy_arguments_boilerplate) \
V(ALIASED_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
aliased_arguments_boilerplate) \
- V(STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
- strict_mode_arguments_boilerplate) \
+ V(STRICT_ARGUMENTS_BOILERPLATE_INDEX, JSObject, \
+ strict_arguments_boilerplate) \
V(MESSAGE_LISTENERS_INDEX, JSObject, message_listeners) \
V(MAKE_MESSAGE_FUN_INDEX, JSFunction, make_message_fun) \
V(GET_STACK_TRACE_LINE_INDEX, JSFunction, get_stack_trace_line_fun) \
@@ -168,6 +170,12 @@
error_message_for_code_gen_from_strings) \
V(RUN_MICROTASKS_INDEX, JSFunction, run_microtasks) \
V(ENQUEUE_EXTERNAL_MICROTASK_INDEX, JSFunction, enqueue_external_microtask) \
+ V(IS_PROMISE_INDEX, JSFunction, is_promise) \
+ V(PROMISE_CREATE_INDEX, JSFunction, promise_create) \
+ V(PROMISE_RESOLVE_INDEX, JSFunction, promise_resolve) \
+ V(PROMISE_REJECT_INDEX, JSFunction, promise_reject) \
+ V(PROMISE_CHAIN_INDEX, JSFunction, promise_chain) \
+ V(PROMISE_CATCH_INDEX, JSFunction, promise_catch) \
V(TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX, JSFunction, \
to_complete_property_descriptor) \
V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
@@ -180,9 +188,8 @@
observers_begin_perform_splice) \
V(OBSERVERS_END_SPLICE_INDEX, JSFunction, \
observers_end_perform_splice) \
- V(GENERATOR_FUNCTION_MAP_INDEX, Map, generator_function_map) \
- V(STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX, Map, \
- strict_mode_generator_function_map) \
+ V(SLOPPY_GENERATOR_FUNCTION_MAP_INDEX, Map, sloppy_generator_function_map) \
+ V(STRICT_GENERATOR_FUNCTION_MAP_INDEX, Map, strict_generator_function_map) \
V(GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX, Map, \
generator_object_prototype_map) \
V(GENERATOR_RESULT_MAP_INDEX, Map, generator_result_map)
@@ -259,14 +266,14 @@
// These slots are only in native contexts.
GLOBAL_PROXY_INDEX = MIN_CONTEXT_SLOTS,
SECURITY_TOKEN_INDEX,
- ARGUMENTS_BOILERPLATE_INDEX,
+ SLOPPY_ARGUMENTS_BOILERPLATE_INDEX,
ALIASED_ARGUMENTS_BOILERPLATE_INDEX,
- STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX,
+ STRICT_ARGUMENTS_BOILERPLATE_INDEX,
REGEXP_RESULT_MAP_INDEX,
- FUNCTION_MAP_INDEX,
- STRICT_MODE_FUNCTION_MAP_INDEX,
- FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
- STRICT_MODE_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
+ SLOPPY_FUNCTION_MAP_INDEX,
+ STRICT_FUNCTION_MAP_INDEX,
+ SLOPPY_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
+ STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX,
INITIAL_OBJECT_PROTOTYPE_INDEX,
INITIAL_ARRAY_PROTOTYPE_INDEX,
BOOLEAN_FUNCTION_INDEX,
@@ -323,6 +330,12 @@
ERROR_MESSAGE_FOR_CODE_GEN_FROM_STRINGS_INDEX,
RUN_MICROTASKS_INDEX,
ENQUEUE_EXTERNAL_MICROTASK_INDEX,
+ IS_PROMISE_INDEX,
+ PROMISE_CREATE_INDEX,
+ PROMISE_RESOLVE_INDEX,
+ PROMISE_REJECT_INDEX,
+ PROMISE_CHAIN_INDEX,
+ PROMISE_CATCH_INDEX,
TO_COMPLETE_PROPERTY_DESCRIPTOR_INDEX,
DERIVED_HAS_TRAP_INDEX,
DERIVED_GET_TRAP_INDEX,
@@ -332,8 +345,8 @@
OBSERVERS_ENQUEUE_SPLICE_INDEX,
OBSERVERS_BEGIN_SPLICE_INDEX,
OBSERVERS_END_SPLICE_INDEX,
- GENERATOR_FUNCTION_MAP_INDEX,
- STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX,
+ SLOPPY_GENERATOR_FUNCTION_MAP_INDEX,
+ STRICT_GENERATOR_FUNCTION_MAP_INDEX,
GENERATOR_OBJECT_PROTOTYPE_MAP_INDEX,
GENERATOR_RESULT_MAP_INDEX,
@@ -493,14 +506,14 @@
return kHeaderSize + index * kPointerSize - kHeapObjectTag;
}
- static int FunctionMapIndex(LanguageMode language_mode, bool is_generator) {
+ static int FunctionMapIndex(StrictMode strict_mode, bool is_generator) {
return is_generator
- ? (language_mode == CLASSIC_MODE
- ? GENERATOR_FUNCTION_MAP_INDEX
- : STRICT_MODE_GENERATOR_FUNCTION_MAP_INDEX)
- : (language_mode == CLASSIC_MODE
- ? FUNCTION_MAP_INDEX
- : STRICT_MODE_FUNCTION_MAP_INDEX);
+ ? (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 const int kSize = kHeaderSize + NATIVE_CONTEXT_SLOTS * kPointerSize;
diff --git a/src/date.cc b/src/date.cc
index 4afd8dc..4d9cf22 100644
--- a/src/date.cc
+++ b/src/date.cc
@@ -62,6 +62,7 @@
after_ = &dst_[1];
local_offset_ms_ = kInvalidLocalOffsetInMs;
ymd_valid_ = false;
+ OS::TimeZoneChanged();
}
diff --git a/src/date.js b/src/date.js
index f3d4af2..5eece68 100644
--- a/src/date.js
+++ b/src/date.js
@@ -46,6 +46,7 @@
function LocalTimezone(t) {
if (NUMBER_IS_NAN(t)) return "";
+ CheckDateCacheCurrent();
if (t == timezone_cache_time) {
return timezone_cache_timezone;
}
@@ -156,6 +157,7 @@
} else if (IS_STRING(year)) {
// Probe the Date cache. If we already have a time value for the
// given time, we re-use that instead of parsing the string again.
+ CheckDateCacheCurrent();
var cache = Date_cache;
if (cache.string === year) {
value = cache.time;
@@ -743,10 +745,22 @@
}
-function ResetDateCache() {
+var date_cache_version_holder;
+var date_cache_version = NAN;
+
+
+function CheckDateCacheCurrent() {
+ if (!date_cache_version_holder) {
+ date_cache_version_holder = %DateCacheVersion();
+ }
+ if (date_cache_version_holder[0] == date_cache_version) {
+ return;
+ }
+ date_cache_version = date_cache_version_holder[0];
+
// Reset the timezone cache:
timezone_cache_time = NAN;
- timezone_cache_timezone = undefined;
+ timezone_cache_timezone = UNDEFINED;
// Reset the date cache:
cache = Date_cache;
diff --git a/src/debug.cc b/src/debug.cc
index 5e740bc..7014129 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -852,7 +852,7 @@
key,
Handle<Object>(global->builtins(), isolate_),
NONE,
- kNonStrictMode),
+ SLOPPY),
false);
// Compile the JavaScript for the debugger in the debugger context.
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc
index 1f645e4..cf3c03d 100644
--- a/src/deoptimizer.cc
+++ b/src/deoptimizer.cc
@@ -392,9 +392,33 @@
element = next;
}
+#ifdef DEBUG
+ // Make sure all activations of optimized code can deopt at their current PC.
+ for (StackFrameIterator it(isolate, isolate->thread_local_top());
+ !it.done(); it.Advance()) {
+ StackFrame::Type type = it.frame()->type();
+ if (type == StackFrame::OPTIMIZED) {
+ Code* code = it.frame()->LookupCode();
+ if (FLAG_trace_deopt) {
+ JSFunction* function =
+ static_cast<OptimizedFrame*>(it.frame())->function();
+ CodeTracer::Scope scope(isolate->GetCodeTracer());
+ PrintF(scope.file(), "[deoptimizer patches for lazy deopt: ");
+ function->PrintName(scope.file());
+ PrintF(scope.file(),
+ " / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
+ }
+ SafepointEntry safepoint = code->GetSafepointEntry(it.frame()->pc());
+ int deopt_index = safepoint.deoptimization_index();
+ CHECK(deopt_index != Safepoint::kNoDeoptimizationIndex);
+ }
+ }
+#endif
+
// TODO(titzer): we need a handle scope only because of the macro assembler,
// which is only used in EnsureCodeForDeoptimizationEntry.
HandleScope scope(isolate);
+
// Now patch all the codes for deoptimization.
for (int i = 0; i < codes.length(); i++) {
// It is finally time to die, code object.
diff --git a/src/elements-kind.cc b/src/elements-kind.cc
index d2abb04..c9480d6 100644
--- a/src/elements-kind.cc
+++ b/src/elements-kind.cc
@@ -66,7 +66,7 @@
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
return kPointerSizeLog2;
}
UNREACHABLE();
diff --git a/src/elements-kind.h b/src/elements-kind.h
index 5a3f00d..32108f5 100644
--- a/src/elements-kind.h
+++ b/src/elements-kind.h
@@ -51,7 +51,7 @@
// The "slow" kind.
DICTIONARY_ELEMENTS,
- NON_STRICT_ARGUMENTS_ELEMENTS,
+ SLOPPY_ARGUMENTS_ELEMENTS,
// The "fast" kind for external arrays
EXTERNAL_INT8_ELEMENTS,
EXTERNAL_UINT8_ELEMENTS,
diff --git a/src/elements.cc b/src/elements.cc
index 2e4667d..7123bca 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -68,7 +68,7 @@
// - FixedFloat64ElementsAccessor
// - FixedUint8ClampedElementsAccessor
// - DictionaryElementsAccessor
-// - NonStrictArgumentsElementsAccessor
+// - SloppyArgumentsElementsAccessor
namespace v8 {
@@ -95,7 +95,7 @@
FixedDoubleArray) \
V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
SeededNumberDictionary) \
- V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \
+ V(SloppyArgumentsElementsAccessor, SLOPPY_ARGUMENTS_ELEMENTS, \
FixedArray) \
V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, \
ExternalInt8Array) \
@@ -920,7 +920,7 @@
KindTraits>(name) {}
protected:
friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
- friend class NonStrictArgumentsElementsAccessor;
+ friend class SloppyArgumentsElementsAccessor;
typedef typename KindTraits::BackingStore BackingStore;
@@ -998,9 +998,9 @@
}
typename KindTraits::BackingStore* backing_store =
KindTraits::BackingStore::cast(elements);
- bool is_non_strict_arguments_elements_map =
- backing_store->map() == heap->non_strict_arguments_elements_map();
- if (is_non_strict_arguments_elements_map) {
+ bool is_sloppy_arguments_elements_map =
+ backing_store->map() == heap->sloppy_arguments_elements_map();
+ if (is_sloppy_arguments_elements_map) {
backing_store = KindTraits::BackingStore::cast(
FixedArray::cast(backing_store)->get(1));
}
@@ -1009,7 +1009,7 @@
? Smi::cast(JSArray::cast(obj)->length())->value()
: backing_store->length());
if (key < length) {
- if (!is_non_strict_arguments_elements_map) {
+ if (!is_sloppy_arguments_elements_map) {
ElementsKind kind = KindTraits::Kind;
if (IsFastPackedElementsKind(kind)) {
MaybeObject* transitioned =
@@ -1152,9 +1152,9 @@
CopyDictionaryToObjectElements(
from, from_start, to, to_kind, to_start, copy_size);
return to->GetHeap()->undefined_value();
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
// TODO(verwaest): This is a temporary hack to support extending
- // NON_STRICT_ARGUMENTS_ELEMENTS in SetFastElementsCapacityAndLength.
+ // SLOPPY_ARGUMENTS_ELEMENTS in SetFastElementsCapacityAndLength.
// This case should be UNREACHABLE().
FixedArray* parameter_map = FixedArray::cast(from);
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
@@ -1282,7 +1282,7 @@
CopyDictionaryToDoubleElements(
from, from_start, to, to_start, copy_size);
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
@@ -1492,7 +1492,7 @@
Heap* heap = isolate->heap();
FixedArray* backing_store = FixedArray::cast(obj->elements());
bool is_arguments =
- (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS);
+ (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS);
if (is_arguments) {
backing_store = FixedArray::cast(backing_store->get(1));
}
@@ -1632,18 +1632,18 @@
};
-class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
- NonStrictArgumentsElementsAccessor,
- ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > {
+class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
+ SloppyArgumentsElementsAccessor,
+ ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> > {
public:
- explicit NonStrictArgumentsElementsAccessor(const char* name)
+ explicit SloppyArgumentsElementsAccessor(const char* name)
: ElementsAccessorBase<
- NonStrictArgumentsElementsAccessor,
- ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {}
+ SloppyArgumentsElementsAccessor,
+ ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
protected:
friend class ElementsAccessorBase<
- NonStrictArgumentsElementsAccessor,
- ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >;
+ SloppyArgumentsElementsAccessor,
+ ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >;
MUST_USE_RESULT static MaybeObject* GetImpl(Object* receiver,
JSObject* obj,
@@ -1859,10 +1859,18 @@
MaybeObject* result = ElementsAccessorSubclass::
SetLengthWithoutNormalize(backing_store, array, smi_length, value);
if (!result->ToObject(&new_length)) return result;
- ASSERT(new_length->IsSmi() || new_length->IsUndefined());
+ // even though the proposed length was a smi, new_length could
+ // still be a heap number because SetLengthWithoutNormalize doesn't
+ // allow the array length property to drop below the index of
+ // non-deletable elements.
+ ASSERT(new_length->IsSmi() || new_length->IsHeapNumber() ||
+ new_length->IsUndefined());
if (new_length->IsSmi()) {
array->set_length(Smi::cast(new_length));
return array;
+ } else if (new_length->IsHeapNumber()) {
+ array->set_length(new_length);
+ return array;
}
} else {
return ThrowArrayLengthRangeError(array->GetHeap());
diff --git a/src/elements.h b/src/elements.h
index 6353aae..9351598 100644
--- a/src/elements.h
+++ b/src/elements.h
@@ -175,7 +175,7 @@
static void TearDown();
protected:
- friend class NonStrictArgumentsElementsAccessor;
+ friend class SloppyArgumentsElementsAccessor;
virtual uint32_t GetCapacity(FixedArrayBase* backing_store) = 0;
diff --git a/src/execution.cc b/src/execution.cc
index 690a4e3..ac848e1 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -163,9 +163,10 @@
}
Handle<JSFunction> func = Handle<JSFunction>::cast(callable);
- // In non-strict mode, convert receiver.
+ // In sloppy mode, convert receiver.
if (convert_receiver && !receiver->IsJSReceiver() &&
- !func->shared()->native() && func->shared()->is_classic_mode()) {
+ !func->shared()->native() &&
+ func->shared()->strict_mode() == SLOPPY) {
if (receiver->IsUndefined() || receiver->IsNull()) {
Object* global = func->context()->global_object()->global_receiver();
// Under some circumstances, 'global' can be the JSBuiltinsObject
diff --git a/src/factory.cc b/src/factory.cc
index 1141229..6f86647 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -927,7 +927,7 @@
static Handle<Map> MapForNewFunction(Isolate *isolate,
Handle<SharedFunctionInfo> function_info) {
Context *context = isolate->context()->native_context();
- int map_index = Context::FunctionMapIndex(function_info->language_mode(),
+ int map_index = Context::FunctionMapIndex(function_info->strict_mode(),
function_info->is_generator());
return Handle<Map>(Map::cast(context->get(map_index)));
}
@@ -1250,8 +1250,7 @@
Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name,
Handle<Code> code) {
- Handle<JSFunction> function = NewFunctionWithoutPrototype(name,
- CLASSIC_MODE);
+ Handle<JSFunction> function = NewFunctionWithoutPrototype(name, SLOPPY);
function->shared()->set_code(*code);
function->set_code(*code);
ASSERT(!function->has_initial_map());
@@ -1627,7 +1626,7 @@
Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->AllocateFunction(*isolate()->function_map(),
+ isolate()->heap()->AllocateFunction(*isolate()->sloppy_function_map(),
*function_share,
*prototype),
JSFunction);
@@ -1644,11 +1643,11 @@
Handle<JSFunction> Factory::NewFunctionWithoutPrototypeHelper(
Handle<String> name,
- LanguageMode language_mode) {
+ StrictMode strict_mode) {
Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
- Handle<Map> map = (language_mode == CLASSIC_MODE)
- ? isolate()->function_without_prototype_map()
- : isolate()->strict_mode_function_without_prototype_map();
+ Handle<Map> map = strict_mode == SLOPPY
+ ? isolate()->sloppy_function_without_prototype_map()
+ : isolate()->strict_function_without_prototype_map();
CALL_HEAP_FUNCTION(isolate(),
isolate()->heap()->AllocateFunction(
*map,
@@ -1660,9 +1659,8 @@
Handle<JSFunction> Factory::NewFunctionWithoutPrototype(
Handle<String> name,
- LanguageMode language_mode) {
- Handle<JSFunction> fun =
- NewFunctionWithoutPrototypeHelper(name, language_mode);
+ StrictMode strict_mode) {
+ Handle<JSFunction> fun = NewFunctionWithoutPrototypeHelper(name, strict_mode);
fun->set_context(isolate()->context()->native_context());
return fun;
}
diff --git a/src/factory.h b/src/factory.h
index 7d1a17a..558ff85 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -377,7 +377,7 @@
Handle<JSFunction> NewFunctionWithoutPrototype(
Handle<String> name,
- LanguageMode language_mode);
+ StrictMode strict_mode);
Handle<JSFunction> NewFunction(Handle<Object> super, bool is_global);
@@ -580,7 +580,7 @@
Handle<JSFunction> NewFunctionWithoutPrototypeHelper(
Handle<String> name,
- LanguageMode language_mode);
+ StrictMode strict_mode);
// Create a new map cache.
Handle<MapCache> NewMapCache(int at_least_space_for);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 8c3f39d..5441a1d 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -893,7 +893,7 @@
#define FLAG FLAG_READONLY
// assembler-arm.h
-DEFINE_bool(enable_ool_constant_pool, false,
+DEFINE_bool(enable_ool_constant_pool, V8_OOL_CONSTANT_POOL,
"enable use of out-of-line constant pools (ARM only)")
// Cleanup...
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index d116bae..165d007 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -802,10 +802,10 @@
int FullCodeGenerator::DeclareGlobalsFlags() {
- ASSERT(DeclareGlobalsLanguageMode::is_valid(language_mode()));
+ ASSERT(DeclareGlobalsStrictMode::is_valid(strict_mode()));
return DeclareGlobalsEvalFlag::encode(is_eval()) |
DeclareGlobalsNativeFlag::encode(is_native()) |
- DeclareGlobalsLanguageMode::encode(language_mode());
+ DeclareGlobalsStrictMode::encode(strict_mode());
}
diff --git a/src/full-codegen.h b/src/full-codegen.h
index bc85d57..f2e39de 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -556,7 +556,7 @@
// Helper functions to EmitVariableAssignment
void EmitStoreToStackLocalOrContextSlot(Variable* var,
MemOperand location);
- void EmitCallStoreContextSlot(Handle<String> name, LanguageMode mode);
+ void EmitCallStoreContextSlot(Handle<String> name, StrictMode strict_mode);
// Complete a named property assignment. The receiver is expected on top
// of the stack and the right-hand-side value in the accumulator.
@@ -602,11 +602,7 @@
Handle<Script> script() { return info_->script(); }
bool is_eval() { return info_->is_eval(); }
bool is_native() { return info_->is_native(); }
- bool is_classic_mode() { return language_mode() == CLASSIC_MODE; }
- StrictModeFlag strict_mode() {
- return is_classic_mode() ? kNonStrictMode : kStrictMode;
- }
- LanguageMode language_mode() { return function()->language_mode(); }
+ StrictMode strict_mode() { return function()->strict_mode(); }
FunctionLiteral* function() { return info_->function(); }
Scope* scope() { return scope_; }
diff --git a/src/func-name-inferrer.h b/src/func-name-inferrer.h
index f57e778..41953ff 100644
--- a/src/func-name-inferrer.h
+++ b/src/func-name-inferrer.h
@@ -28,9 +28,13 @@
#ifndef V8_FUNC_NAME_INFERRER_H_
#define V8_FUNC_NAME_INFERRER_H_
+#include "handles.h"
+#include "zone.h"
+
namespace v8 {
namespace internal {
+class FunctionLiteral;
class Isolate;
// FuncNameInferrer is a stateful class that is used to perform name
diff --git a/src/global-handles.h b/src/global-handles.h
index a406451..f46a22a 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -340,6 +340,7 @@
enum SingletonHandle {
I18N_TEMPLATE_ONE,
I18N_TEMPLATE_TWO,
+ DATE_CACHE_VERSION,
NUMBER_OF_SINGLETON_HANDLES
};
diff --git a/src/globals.h b/src/globals.h
index ac5b710..85b5e6b 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -162,6 +162,9 @@
#error Unknown target architecture endiannes
#endif
+// Determine whether the architecture uses an out-of-line constant pool.
+#define V8_OOL_CONSTANT_POOL 0
+
// Support for alternative bool type. This is only enabled if the code is
// compiled with USE_MYBOOL defined. This catches some nasty type bugs.
// For instance, 'bool b = "false";' results in b == true! This is a hidden
@@ -407,34 +410,9 @@
// -----------------------------------------------------------------------------
// Declarations for use in both the preparser and the rest of V8.
-// The different language modes that V8 implements. ES5 defines two language
-// modes: an unrestricted mode respectively a strict mode which are indicated by
-// CLASSIC_MODE respectively STRICT_MODE in the enum. The harmony spec drafts
-// for the next ES standard specify a new third mode which is called 'extended
-// mode'. The extended mode is only available if the harmony flag is set. It is
-// based on the 'strict mode' and adds new functionality to it. This means that
-// most of the semantics of these two modes coincide.
-//
-// In the current draft the term 'base code' is used to refer to code that is
-// neither in strict nor extended mode. However, the more distinguishing term
-// 'classic mode' is used in V8 instead to avoid mix-ups.
-
-enum LanguageMode {
- CLASSIC_MODE,
- STRICT_MODE,
- EXTENDED_MODE
-};
-
-
// The Strict Mode (ECMA-262 5th edition, 4.2.2).
-//
-// This flag is used in the backend to represent the language mode. So far
-// there is no semantic difference between the strict and the extended mode in
-// the backend, so both modes are represented by the kStrictMode value.
-enum StrictModeFlag {
- kNonStrictMode,
- kStrictMode
-};
+
+enum StrictMode { SLOPPY, STRICT };
} } // namespace v8::internal
diff --git a/src/handles.cc b/src/handles.cc
index 47bab25..899f9bf 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -509,7 +509,7 @@
Isolate* isolate = object->GetIsolate();
Handle<FixedArray> content = isolate->factory()->empty_fixed_array();
Handle<JSObject> arguments_boilerplate = Handle<JSObject>(
- isolate->context()->native_context()->arguments_boilerplate(),
+ isolate->context()->native_context()->sloppy_arguments_boilerplate(),
isolate);
Handle<JSFunction> arguments_function = Handle<JSFunction>(
JSFunction::cast(arguments_boilerplate->map()->constructor()),
diff --git a/src/harmony-array.js b/src/harmony-array.js
index 2cedeba..d37d875 100644
--- a/src/harmony-array.js
+++ b/src/harmony-array.js
@@ -51,7 +51,7 @@
if (IS_NULL_OR_UNDEFINED(thisArg)) {
thisArg = %GetDefaultReceiver(predicate) || thisArg;
- } else if (!IS_SPEC_OBJECT(thisArg) && %IsClassicModeFunction(predicate)) {
+ } else if (!IS_SPEC_OBJECT(thisArg) && %IsSloppyModeFunction(predicate)) {
thisArg = ToObject(thisArg);
}
@@ -86,7 +86,7 @@
if (IS_NULL_OR_UNDEFINED(thisArg)) {
thisArg = %GetDefaultReceiver(predicate) || thisArg;
- } else if (!IS_SPEC_OBJECT(thisArg) && %IsClassicModeFunction(predicate)) {
+ } else if (!IS_SPEC_OBJECT(thisArg) && %IsSloppyModeFunction(predicate)) {
thisArg = ToObject(thisArg);
}
diff --git a/src/heap.cc b/src/heap.cc
index d54a2d6..25f7121 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -614,6 +614,9 @@
if (FLAG_code_stats) ReportCodeStatistics("After GC");
#endif
if (FLAG_deopt_every_n_garbage_collections > 0) {
+ // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that
+ // the topmost optimized frame can be deoptimized safely, because it
+ // might not have a lazy bailout point right after its current PC.
if (++gcs_since_last_deopt_ == FLAG_deopt_every_n_garbage_collections) {
Deoptimizer::DeoptimizeAll(isolate());
gcs_since_last_deopt_ = 0;
@@ -2866,7 +2869,7 @@
TYPED_ARRAYS(ALLOCATE_FIXED_TYPED_ARRAY_MAP)
#undef ALLOCATE_FIXED_TYPED_ARRAY_MAP
- ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, non_strict_arguments_elements)
+ ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, sloppy_arguments_elements)
ALLOCATE_VARSIZE_MAP(CODE_TYPE, code)
@@ -4277,16 +4280,15 @@
JSObject* boilerplate;
int arguments_object_size;
bool strict_mode_callee = callee->IsJSFunction() &&
- !JSFunction::cast(callee)->shared()->is_classic_mode();
+ JSFunction::cast(callee)->shared()->strict_mode() == STRICT;
if (strict_mode_callee) {
boilerplate =
- isolate()->context()->native_context()->
- strict_mode_arguments_boilerplate();
- arguments_object_size = kArgumentsObjectSizeStrict;
+ isolate()->context()->native_context()->strict_arguments_boilerplate();
+ arguments_object_size = kStrictArgumentsObjectSize;
} else {
boilerplate =
- isolate()->context()->native_context()->arguments_boilerplate();
- arguments_object_size = kArgumentsObjectSize;
+ isolate()->context()->native_context()->sloppy_arguments_boilerplate();
+ arguments_object_size = kSloppyArgumentsObjectSize;
}
// Check that the size of the boilerplate matches our
@@ -4312,7 +4314,7 @@
JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsLengthIndex,
Smi::FromInt(length),
SKIP_WRITE_BARRIER);
- // Set the callee property for non-strict mode arguments object only.
+ // Set the callee property for sloppy mode arguments object only.
if (!strict_mode_callee) {
JSObject::cast(result)->InObjectPropertyAtPut(kArgumentsCalleeIndex,
callee);
diff --git a/src/heap.h b/src/heap.h
index 2292464..304e1f8 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -164,7 +164,7 @@
V(Map, fixed_float32_array_map, FixedFloat32ArrayMap) \
V(Map, fixed_float64_array_map, FixedFloat64ArrayMap) \
V(Map, fixed_uint8_clamped_array_map, FixedUint8ClampedArrayMap) \
- V(Map, non_strict_arguments_elements_map, NonStrictArgumentsElementsMap) \
+ V(Map, sloppy_arguments_elements_map, SloppyArgumentsElementsMap) \
V(Map, function_context_map, FunctionContextMap) \
V(Map, catch_context_map, CatchContextMap) \
V(Map, with_context_map, WithContextMap) \
@@ -250,7 +250,7 @@
V(empty_constant_pool_array) \
V(arguments_marker) \
V(symbol_map) \
- V(non_strict_arguments_elements_map) \
+ V(sloppy_arguments_elements_map) \
V(function_context_map) \
V(catch_context_map) \
V(with_context_map) \
@@ -1078,15 +1078,15 @@
Object* prototype,
PretenureFlag pretenure = TENURED);
- // Arguments object size.
- static const int kArgumentsObjectSize =
+ // Sloppy mode arguments object size.
+ static const int kSloppyArgumentsObjectSize =
JSObject::kHeaderSize + 2 * kPointerSize;
// Strict mode arguments has no callee so it is smaller.
- static const int kArgumentsObjectSizeStrict =
+ static const int kStrictArgumentsObjectSize =
JSObject::kHeaderSize + 1 * kPointerSize;
// Indicies for direct access into argument objects.
static const int kArgumentsLengthIndex = 0;
- // callee is only valid in non-strict mode.
+ // callee is only valid in sloppy mode.
static const int kArgumentsCalleeIndex = 1;
// Allocates an arguments object - optionally with an elements array.
diff --git a/src/hydrogen-gvn.cc b/src/hydrogen-gvn.cc
index 4c98015..827ad27 100644
--- a/src/hydrogen-gvn.cc
+++ b/src/hydrogen-gvn.cc
@@ -592,7 +592,9 @@
graph()->use_optimistic_licm() ? "yes" : "no");
for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
HBasicBlock* block = graph()->blocks()->at(i);
- if (block->IsLoopHeader()) {
+ if (block->IsLoopHeader() &&
+ block->IsReachable() &&
+ !block->IsDeoptimizing()) {
SideEffects side_effects = loop_side_effects_[block->block_id()];
if (FLAG_trace_gvn) {
HeapStringAllocator allocator;
@@ -616,6 +618,7 @@
HBasicBlock* block,
HBasicBlock* loop_header,
SideEffects loop_kills) {
+ if (!block->IsReachable() || block->IsDeoptimizing()) return;
HBasicBlock* pre_header = loop_header->predecessors()->at(0);
if (FLAG_trace_gvn) {
HeapStringAllocator allocator;
@@ -680,10 +683,8 @@
bool HGlobalValueNumberingPhase::ShouldMove(HInstruction* instr,
HBasicBlock* loop_header) {
- // If we've disabled code motion or we're in a block that unconditionally
- // deoptimizes, don't move any instructions.
- return AllowCodeMotion() && !instr->block()->IsDeoptimizing() &&
- instr->block()->IsReachable();
+ // If we've disabled code motion, don't move any instructions.
+ return AllowCodeMotion();
}
@@ -776,20 +777,18 @@
}
GvnBasicBlockState* next_dominated(Zone* zone) {
- dominated_index_++;
- if (dominated_index_ == length_ - 1) {
- // No need to copy the map for the last child in the dominator tree.
- Initialize(block_->dominated_blocks()->at(dominated_index_),
- map(),
- dominators(),
- false,
- zone);
- return this;
- } else if (dominated_index_ < length_) {
- return push(zone, block_->dominated_blocks()->at(dominated_index_));
- } else {
- return NULL;
+ while (++dominated_index_ < length_) {
+ HBasicBlock* block = block_->dominated_blocks()->at(dominated_index_);
+ if (block->IsReachable()) {
+ if (dominated_index_ == length_ - 1) {
+ // No need to copy the map for the last child in the dominator tree.
+ Initialize(block, map(), dominators(), false, zone);
+ return this;
+ }
+ return push(zone, block);
+ }
}
+ return NULL;
}
GvnBasicBlockState* push(Zone* zone, HBasicBlock* block) {
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 79c7964..59fa3b1 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -30,6 +30,7 @@
#include "double.h"
#include "factory.h"
#include "hydrogen-infer-representation.h"
+#include "property-details-inl.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/lithium-ia32.h"
@@ -1433,19 +1434,19 @@
HInstruction* HForceRepresentation::New(Zone* zone, HValue* context,
- HValue* value, Representation required_representation) {
+ HValue* value, Representation representation) {
if (FLAG_fold_constants && value->IsConstant()) {
HConstant* c = HConstant::cast(value);
if (c->HasNumberValue()) {
double double_res = c->DoubleValue();
- if (IsInt32Double(double_res)) {
+ if (representation.CanContainDouble(double_res)) {
return HConstant::New(zone, context,
static_cast<int32_t>(double_res),
- required_representation);
+ representation);
}
}
}
- return new(zone) HForceRepresentation(value, required_representation);
+ return new(zone) HForceRepresentation(value, representation);
}
@@ -1788,7 +1789,7 @@
}
-Range* HDiv::InferRange(Zone* zone) {
+Range* HBinaryOperation::InferRangeForDiv(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
Range* b = right()->range();
@@ -1797,11 +1798,11 @@
(a->CanBeMinusZero() ||
(a->CanBeZero() && b->CanBeNegative())));
if (!a->Includes(kMinInt) || !b->Includes(-1)) {
- ClearFlag(HValue::kCanOverflow);
+ ClearFlag(kCanOverflow);
}
if (!b->CanBeZero()) {
- ClearFlag(HValue::kCanBeDivByZero);
+ ClearFlag(kCanBeDivByZero);
}
return result;
} else {
@@ -1810,6 +1811,16 @@
}
+Range* HDiv::InferRange(Zone* zone) {
+ return InferRangeForDiv(zone);
+}
+
+
+Range* HMathFloorOfDiv::InferRange(Zone* zone) {
+ return InferRangeForDiv(zone);
+}
+
+
Range* HMod::InferRange(Zone* zone) {
if (representation().IsInteger32()) {
Range* a = left()->range();
@@ -2460,6 +2471,7 @@
void HSimulate::ReplayEnvironment(HEnvironment* env) {
+ if (done_with_replay_) return;
ASSERT(env != NULL);
env->set_ast_id(ast_id());
env->Drop(pop_count());
@@ -2471,6 +2483,7 @@
env->Push(value);
}
}
+ done_with_replay_ = true;
}
@@ -3056,7 +3069,7 @@
bool HCompareObjectEqAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && left()->IsConstant() && right()->IsConstant()) {
- *block = HConstant::cast(left())->Equals(HConstant::cast(right()))
+ *block = HConstant::cast(left())->DataEquals(HConstant::cast(right()))
? FirstSuccessor() : SecondSuccessor();
return true;
}
@@ -3099,17 +3112,6 @@
}
-bool HIsSmiAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
- if (FLAG_fold_constants && value()->IsConstant()) {
- *block = HConstant::cast(value())->HasSmiValue()
- ? FirstSuccessor() : SecondSuccessor();
- return true;
- }
- *block = NULL;
- return false;
-}
-
-
bool HIsUndetectableAndBranch::KnownSuccessorBlock(HBasicBlock** block) {
if (FLAG_fold_constants && value()->IsConstant()) {
*block = HConstant::cast(value())->IsUndetectable()
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index e8ae22d..8d5d271 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -855,7 +855,6 @@
// TODO(svenpanne) We should really use the null object pattern here.
bool HasRange() const { return range_ != NULL; }
bool CanBeNegative() const { return !HasRange() || range()->CanBeNegative(); }
- bool CanBeZero() const { return !HasRange() || range()->CanBeZero(); }
bool RangeCanInclude(int value) const {
return !HasRange() || range()->Includes(value);
}
@@ -1878,7 +1877,8 @@
values_(2, zone),
assigned_indexes_(2, zone),
zone_(zone),
- removable_(removable) {}
+ removable_(removable),
+ done_with_replay_(false) {}
~HSimulate() {}
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -1961,7 +1961,8 @@
ZoneList<HValue*> values_;
ZoneList<int> assigned_indexes_;
Zone* zone_;
- RemovableSimulate removable_;
+ RemovableSimulate removable_ : 2;
+ bool done_with_replay_ : 1;
#ifdef DEBUG
Handle<JSFunction> closure_;
@@ -3585,15 +3586,6 @@
return object_.IsInitialized() && object_ == other;
}
-#ifdef DEBUG
- virtual void Verify() V8_OVERRIDE { }
-#endif
-
- DECLARE_CONCRETE_INSTRUCTION(Constant)
-
- protected:
- virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
-
virtual bool DataEquals(HValue* other) V8_OVERRIDE {
HConstant* other_constant = HConstant::cast(other);
if (has_int32_value_) {
@@ -3618,6 +3610,15 @@
}
}
+#ifdef DEBUG
+ virtual void Verify() V8_OVERRIDE { }
+#endif
+
+ DECLARE_CONCRETE_INSTRUCTION(Constant)
+
+ protected:
+ virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
+
private:
friend class HGraph;
HConstant(Handle<Object> handle, Representation r = Representation::None());
@@ -3763,6 +3764,9 @@
DECLARE_ABSTRACT_INSTRUCTION(BinaryOperation)
+ protected:
+ Range* InferRangeForDiv(Zone* zone);
+
private:
bool IgnoreObservedOutputRepresentation(Representation current_rep);
@@ -4049,7 +4053,6 @@
}
virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
- if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
if (to.IsTagged() &&
(left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
SetAllSideEffects();
@@ -4058,6 +4061,7 @@
ClearAllSideEffects();
SetFlag(kUseGVN);
}
+ if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
}
virtual void UpdateRepresentation(Representation new_rep,
@@ -4103,12 +4107,12 @@
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
SetFlag(kCanOverflow);
- if (!right->IsConstant()) {
- SetFlag(kCanBeDivByZero);
- }
+ SetFlag(kCanBeDivByZero);
SetFlag(kAllowUndefinedAsNaN);
}
+ virtual Range* InferRange(Zone* zone) V8_OVERRIDE;
+
virtual bool IsDeletable() const V8_OVERRIDE { return true; }
};
@@ -4123,7 +4127,6 @@
}
virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
- if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
if (to.IsTagged() &&
(left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved())) {
SetAllSideEffects();
@@ -4132,6 +4135,7 @@
ClearAllSideEffects();
SetFlag(kUseGVN);
}
+ if (to.IsTagged()) SetChangesFlag(kNewSpacePromotion);
}
DECLARE_ABSTRACT_INSTRUCTION(ArithmeticBinaryOperation)
@@ -4281,24 +4285,6 @@
class HCompareObjectEqAndBranch : public HTemplateControlInstruction<2, 2> {
public:
- HCompareObjectEqAndBranch(HValue* left,
- HValue* right,
- HBasicBlock* true_target = NULL,
- HBasicBlock* false_target = NULL) {
- // TODO(danno): make this private when the IfBuilder properly constructs
- // control flow instructions.
- ASSERT(!left->IsConstant() ||
- (!HConstant::cast(left)->HasInteger32Value() ||
- HConstant::cast(left)->HasSmiValue()));
- ASSERT(!right->IsConstant() ||
- (!HConstant::cast(right)->HasInteger32Value() ||
- HConstant::cast(right)->HasSmiValue()));
- SetOperandAt(0, left);
- SetOperandAt(1, right);
- SetSuccessorAt(0, true_target);
- SetSuccessorAt(1, false_target);
- }
-
DECLARE_INSTRUCTION_FACTORY_P2(HCompareObjectEqAndBranch, HValue*, HValue*);
DECLARE_INSTRUCTION_FACTORY_P4(HCompareObjectEqAndBranch, HValue*, HValue*,
HBasicBlock*, HBasicBlock*);
@@ -4319,6 +4305,23 @@
}
DECLARE_CONCRETE_INSTRUCTION(CompareObjectEqAndBranch)
+
+ private:
+ HCompareObjectEqAndBranch(HValue* left,
+ HValue* right,
+ HBasicBlock* true_target = NULL,
+ HBasicBlock* false_target = NULL) {
+ ASSERT(!left->IsConstant() ||
+ (!HConstant::cast(left)->HasInteger32Value() ||
+ HConstant::cast(left)->HasSmiValue()));
+ ASSERT(!right->IsConstant() ||
+ (!HConstant::cast(right)->HasInteger32Value() ||
+ HConstant::cast(right)->HasSmiValue()));
+ SetOperandAt(0, left);
+ SetOperandAt(1, right);
+ SetSuccessorAt(0, true_target);
+ SetSuccessorAt(1, false_target);
+ }
};
@@ -4381,8 +4384,6 @@
return Representation::Tagged();
}
- virtual bool KnownSuccessorBlock(HBasicBlock** block) V8_OVERRIDE;
-
protected:
virtual bool DataEquals(HValue* other) V8_OVERRIDE { return true; }
virtual int RedefinedOperandIndex() { return 0; }
@@ -4716,10 +4717,6 @@
}
virtual void RepresentationChanged(Representation to) V8_OVERRIDE {
- if (to.IsTagged()) {
- SetChangesFlag(kNewSpacePromotion);
- ClearFlag(kAllowUndefinedAsNaN);
- }
if (to.IsTagged() &&
(left()->ToNumberCanBeObserved() || right()->ToNumberCanBeObserved() ||
left()->ToStringCanBeObserved() || right()->ToStringCanBeObserved())) {
@@ -4729,6 +4726,10 @@
ClearAllSideEffects();
SetFlag(kUseGVN);
}
+ if (to.IsTagged()) {
+ SetChangesFlag(kNewSpacePromotion);
+ ClearFlag(kAllowUndefinedAsNaN);
+ }
}
virtual Representation RepresentationFromInputs() V8_OVERRIDE;
@@ -5684,10 +5685,10 @@
ASSERT(var->IsContextSlot());
switch (var->mode()) {
case LET:
- case CONST_HARMONY:
+ case CONST:
mode_ = kCheckDeoptimize;
break;
- case CONST:
+ case CONST_LEGACY:
mode_ = kCheckReturnUndefined;
break;
default:
@@ -6638,12 +6639,12 @@
public:
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreNamedGeneric, HValue*,
Handle<String>, HValue*,
- StrictModeFlag);
+ StrictMode);
HValue* object() { return OperandAt(0); }
HValue* value() { return OperandAt(1); }
HValue* context() { return OperandAt(2); }
Handle<String> name() { return name_; }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
+ StrictMode strict_mode() { return strict_mode_; }
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
@@ -6658,9 +6659,9 @@
HValue* object,
Handle<String> name,
HValue* value,
- StrictModeFlag strict_mode_flag)
+ StrictMode strict_mode)
: name_(name),
- strict_mode_flag_(strict_mode_flag) {
+ strict_mode_(strict_mode) {
SetOperandAt(0, object);
SetOperandAt(1, value);
SetOperandAt(2, context);
@@ -6668,7 +6669,7 @@
}
Handle<String> name_;
- StrictModeFlag strict_mode_flag_;
+ StrictMode strict_mode_;
};
@@ -6850,13 +6851,13 @@
class HStoreKeyedGeneric V8_FINAL : public HTemplateInstruction<4> {
public:
DECLARE_INSTRUCTION_WITH_CONTEXT_FACTORY_P4(HStoreKeyedGeneric, HValue*,
- HValue*, HValue*, StrictModeFlag);
+ HValue*, HValue*, StrictMode);
HValue* object() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
HValue* value() { return OperandAt(2); }
HValue* context() { return OperandAt(3); }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
+ StrictMode strict_mode() { return strict_mode_; }
virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
// tagged[tagged] = tagged
@@ -6872,8 +6873,8 @@
HValue* object,
HValue* key,
HValue* value,
- StrictModeFlag strict_mode_flag)
- : strict_mode_flag_(strict_mode_flag) {
+ StrictMode strict_mode)
+ : strict_mode_(strict_mode) {
SetOperandAt(0, object);
SetOperandAt(1, key);
SetOperandAt(2, value);
@@ -6881,7 +6882,7 @@
SetAllSideEffects();
}
- StrictModeFlag strict_mode_flag_;
+ StrictMode strict_mode_;
};
@@ -7169,7 +7170,7 @@
bool pretenure() const { return pretenure_; }
bool has_no_literals() const { return has_no_literals_; }
bool is_generator() const { return is_generator_; }
- LanguageMode language_mode() const { return language_mode_; }
+ StrictMode strict_mode() const { return strict_mode_; }
private:
HFunctionLiteral(HValue* context,
@@ -7180,7 +7181,7 @@
pretenure_(pretenure),
has_no_literals_(shared->num_literals() == 0),
is_generator_(shared->is_generator()),
- language_mode_(shared->language_mode()) {
+ strict_mode_(shared->strict_mode()) {
SetOperandAt(0, context);
set_representation(Representation::Tagged());
SetChangesFlag(kNewSpacePromotion);
@@ -7192,7 +7193,7 @@
bool pretenure_ : 1;
bool has_no_literals_ : 1;
bool is_generator_ : 1;
- LanguageMode language_mode_;
+ StrictMode strict_mode_;
};
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 4dd9955..ce5ad80 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1282,7 +1282,7 @@
Handle<JSFunction> f = Handle<JSFunction>::cast(
HConstant::cast(function)->handle(isolate()));
SharedFunctionInfo* shared = f->shared();
- if (!shared->is_classic_mode() || shared->native()) return object;
+ if (shared->strict_mode() == STRICT || shared->native()) return object;
}
return Add<HWrapReceiver>(object, function);
}
@@ -5584,7 +5584,7 @@
static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) {
return type->Is(Type::NumberOrString()) &&
- target->shared()->is_classic_mode() &&
+ target->shared()->strict_mode() == SLOPPY &&
!target->shared()->native();
}
@@ -5925,7 +5925,7 @@
HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
HStoreNamedGeneric* instr =
Add<HStoreNamedGeneric>(global_object, var->name(),
- value, function_strict_mode_flag());
+ value, function_strict_mode());
USE(instr);
ASSERT(instr->HasObservableSideEffects());
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
@@ -5960,7 +5960,7 @@
case Variable::PARAMETER:
case Variable::LOCAL:
- if (var->mode() == CONST) {
+ if (var->mode() == CONST_LEGACY) {
return Bailout(kUnsupportedConstCompoundAssignment);
}
BindIfLive(var, Top());
@@ -5989,11 +5989,11 @@
mode = HStoreContextSlot::kCheckDeoptimize;
break;
case CONST:
- return ast_context()->ReturnValue(Pop());
- case CONST_HARMONY:
// This case is checked statically so no need to
// perform checks here
UNREACHABLE();
+ case CONST_LEGACY:
+ return ast_context()->ReturnValue(Pop());
default:
mode = HStoreContextSlot::kNoCheck;
}
@@ -6058,6 +6058,10 @@
if (var->mode() == CONST) {
if (expr->op() != Token::INIT_CONST) {
+ return Bailout(kNonInitializerAssignmentToConst);
+ }
+ } else if (var->mode() == CONST_LEGACY) {
+ if (expr->op() != Token::INIT_CONST_LEGACY) {
CHECK_ALIVE(VisitForValue(expr->value()));
return ast_context()->ReturnValue(Pop());
}
@@ -6068,10 +6072,6 @@
HValue* old_value = environment()->Lookup(var);
Add<HUseConst>(old_value);
}
- } else if (var->mode() == CONST_HARMONY) {
- if (expr->op() != Token::INIT_CONST_HARMONY) {
- return Bailout(kNonInitializerAssignmentToConst);
- }
}
if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
@@ -6127,20 +6127,20 @@
mode = HStoreContextSlot::kCheckDeoptimize;
break;
case CONST:
- return ast_context()->ReturnValue(Pop());
- case CONST_HARMONY:
// This case is checked statically so no need to
// perform checks here
UNREACHABLE();
+ case CONST_LEGACY:
+ return ast_context()->ReturnValue(Pop());
default:
mode = HStoreContextSlot::kNoCheck;
}
} else if (expr->op() == Token::INIT_VAR ||
expr->op() == Token::INIT_LET ||
- expr->op() == Token::INIT_CONST_HARMONY) {
+ expr->op() == Token::INIT_CONST) {
mode = HStoreContextSlot::kNoCheck;
} else {
- ASSERT(expr->op() == Token::INIT_CONST);
+ ASSERT(expr->op() == Token::INIT_CONST_LEGACY);
mode = HStoreContextSlot::kCheckIgnoreAssignment;
}
@@ -6234,8 +6234,7 @@
if (access_type == LOAD) {
return New<HLoadNamedGeneric>(object, name);
} else {
- return New<HStoreNamedGeneric>(
- object, name, value, function_strict_mode_flag());
+ return New<HStoreNamedGeneric>(object, name, value, function_strict_mode());
}
}
@@ -6249,8 +6248,7 @@
if (access_type == LOAD) {
return New<HLoadKeyedGeneric>(object, key);
} else {
- return New<HStoreKeyedGeneric>(
- object, key, value, function_strict_mode_flag());
+ return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode());
}
}
@@ -7937,7 +7935,7 @@
HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
Handle<JSFunction> target) {
SharedFunctionInfo* shared = target->shared();
- if (shared->is_classic_mode() && !shared->native()) {
+ if (shared->strict_mode() == SLOPPY && !shared->native()) {
// Cannot embed a direct reference to the global proxy
// as is it dropped on deserialization.
CHECK(!Serializer::enabled());
@@ -8646,7 +8644,7 @@
HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
Add<HPushArgument>(obj);
Add<HPushArgument>(key);
- Add<HPushArgument>(Add<HConstant>(function_strict_mode_flag()));
+ Add<HPushArgument>(Add<HConstant>(function_strict_mode()));
// TODO(olivf) InvokeFunction produces a check for the parameter count,
// even though we are certain to pass the correct number of arguments here.
HInstruction* instr = New<HInvokeFunction>(function, 3);
@@ -8810,7 +8808,7 @@
if (proxy != NULL) {
Variable* var = proxy->var();
- if (var->mode() == CONST) {
+ if (var->mode() == CONST_LEGACY) {
return Bailout(kUnsupportedCountOperationWithConst);
}
// Argument of the count operation is a variable, not a property.
@@ -10020,7 +10018,7 @@
for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
- DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
+ DeclareGlobalsStrictMode::encode(current_info()->strict_mode());
Add<HDeclareGlobals>(array, flags);
globals_.Clear();
}
@@ -10032,7 +10030,7 @@
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
- bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
+ bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
case Variable::UNALLOCATED:
globals_.Add(variable->name(), zone());
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 9c6192b..4d538f4 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -2109,9 +2109,8 @@
void ClearInlinedTestContext() {
function_state()->ClearInlinedTestContext();
}
- StrictModeFlag function_strict_mode_flag() {
- return function_state()->compilation_info()->is_classic_mode()
- ? kNonStrictMode : kStrictMode;
+ StrictMode function_strict_mode() {
+ return function_state()->compilation_info()->strict_mode();
}
// Generators for inline runtime functions.
diff --git a/src/i18n.cc b/src/i18n.cc
index 5c97c6b..d5ea77d 100644
--- a/src/i18n.cc
+++ b/src/i18n.cc
@@ -163,7 +163,7 @@
reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
pattern.length())),
NONE,
- kNonStrictMode);
+ SLOPPY);
// Set time zone and calendar.
const icu::Calendar* calendar = date_format->getCalendar();
@@ -173,7 +173,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("calendar")),
isolate->factory()->NewStringFromAscii(CStrVector(calendar_name)),
NONE,
- kNonStrictMode);
+ SLOPPY);
const icu::TimeZone& tz = calendar->getTimeZone();
icu::UnicodeString time_zone;
@@ -188,7 +188,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("timeZone")),
isolate->factory()->NewStringFromAscii(CStrVector("UTC")),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
JSObject::SetProperty(
resolved,
@@ -199,7 +199,7 @@
canonical_time_zone.getBuffer()),
canonical_time_zone.length())),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
}
@@ -216,14 +216,14 @@
isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
isolate->factory()->NewStringFromAscii(CStrVector(ns)),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
isolate->factory()->undefined_value(),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
delete numbering_system;
@@ -238,7 +238,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector(result)),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
@@ -246,7 +246,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector("und")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
}
@@ -389,7 +389,7 @@
reinterpret_cast<const uint16_t*>(pattern.getBuffer()),
pattern.length())),
NONE,
- kNonStrictMode);
+ SLOPPY);
// Set resolved currency code in options.currency if not empty.
icu::UnicodeString currency(number_format->getCurrency());
@@ -402,7 +402,7 @@
reinterpret_cast<const uint16_t*>(currency.getBuffer()),
currency.length())),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
// Ugly hack. ICU doesn't expose numbering system in any way, so we have
@@ -418,14 +418,14 @@
isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
isolate->factory()->NewStringFromAscii(CStrVector(ns)),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("numberingSystem")),
isolate->factory()->undefined_value(),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
delete numbering_system;
@@ -434,7 +434,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("useGrouping")),
isolate->factory()->ToBoolean(number_format->isGroupingUsed()),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
@@ -443,7 +443,7 @@
isolate->factory()->NewNumberFromInt(
number_format->getMinimumIntegerDigits()),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
@@ -452,7 +452,7 @@
isolate->factory()->NewNumberFromInt(
number_format->getMinimumFractionDigits()),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
@@ -461,7 +461,7 @@
isolate->factory()->NewNumberFromInt(
number_format->getMaximumFractionDigits()),
NONE,
- kNonStrictMode);
+ SLOPPY);
Handle<String> key = isolate->factory()->NewStringFromAscii(
CStrVector("minimumSignificantDigits"));
@@ -473,7 +473,7 @@
isolate->factory()->NewNumberFromInt(
number_format->getMinimumSignificantDigits()),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
key = isolate->factory()->NewStringFromAscii(
@@ -486,7 +486,7 @@
isolate->factory()->NewNumberFromInt(
number_format->getMaximumSignificantDigits()),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
// Set the locale
@@ -500,7 +500,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector(result)),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
@@ -508,7 +508,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector("und")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
}
@@ -589,7 +589,7 @@
isolate->factory()->ToBoolean(
collator->getAttribute(UCOL_NUMERIC_COLLATION, status) == UCOL_ON),
NONE,
- kNonStrictMode);
+ SLOPPY);
switch (collator->getAttribute(UCOL_CASE_FIRST, status)) {
case UCOL_LOWER_FIRST:
@@ -598,7 +598,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
isolate->factory()->NewStringFromAscii(CStrVector("lower")),
NONE,
- kNonStrictMode);
+ SLOPPY);
break;
case UCOL_UPPER_FIRST:
JSObject::SetProperty(
@@ -606,7 +606,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
isolate->factory()->NewStringFromAscii(CStrVector("upper")),
NONE,
- kNonStrictMode);
+ SLOPPY);
break;
default:
JSObject::SetProperty(
@@ -614,7 +614,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("caseFirst")),
isolate->factory()->NewStringFromAscii(CStrVector("false")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
switch (collator->getAttribute(UCOL_STRENGTH, status)) {
@@ -624,7 +624,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("strength")),
isolate->factory()->NewStringFromAscii(CStrVector("primary")),
NONE,
- kNonStrictMode);
+ SLOPPY);
// case level: true + s1 -> case, s1 -> base.
if (UCOL_ON == collator->getAttribute(UCOL_CASE_LEVEL, status)) {
@@ -633,14 +633,14 @@
isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
isolate->factory()->NewStringFromAscii(CStrVector("case")),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
isolate->factory()->NewStringFromAscii(CStrVector("base")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
break;
}
@@ -650,13 +650,13 @@
isolate->factory()->NewStringFromAscii(CStrVector("strength")),
isolate->factory()->NewStringFromAscii(CStrVector("secondary")),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
isolate->factory()->NewStringFromAscii(CStrVector("accent")),
NONE,
- kNonStrictMode);
+ SLOPPY);
break;
case UCOL_TERTIARY:
JSObject::SetProperty(
@@ -664,13 +664,13 @@
isolate->factory()->NewStringFromAscii(CStrVector("strength")),
isolate->factory()->NewStringFromAscii(CStrVector("tertiary")),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
isolate->factory()->NewStringFromAscii(CStrVector("variant")),
NONE,
- kNonStrictMode);
+ SLOPPY);
break;
case UCOL_QUATERNARY:
// We shouldn't get quaternary and identical from ICU, but if we do
@@ -680,13 +680,13 @@
isolate->factory()->NewStringFromAscii(CStrVector("strength")),
isolate->factory()->NewStringFromAscii(CStrVector("quaternary")),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
isolate->factory()->NewStringFromAscii(CStrVector("variant")),
NONE,
- kNonStrictMode);
+ SLOPPY);
break;
default:
JSObject::SetProperty(
@@ -694,13 +694,13 @@
isolate->factory()->NewStringFromAscii(CStrVector("strength")),
isolate->factory()->NewStringFromAscii(CStrVector("identical")),
NONE,
- kNonStrictMode);
+ SLOPPY);
JSObject::SetProperty(
resolved,
isolate->factory()->NewStringFromAscii(CStrVector("sensitivity")),
isolate->factory()->NewStringFromAscii(CStrVector("variant")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
JSObject::SetProperty(
@@ -709,7 +709,7 @@
isolate->factory()->ToBoolean(collator->getAttribute(
UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED),
NONE,
- kNonStrictMode);
+ SLOPPY);
// Set the locale
char result[ULOC_FULLNAME_CAPACITY];
@@ -722,7 +722,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector(result)),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
@@ -730,7 +730,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector("und")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
}
@@ -785,7 +785,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector(result)),
NONE,
- kNonStrictMode);
+ SLOPPY);
} else {
// This would never happen, since we got the locale from ICU.
JSObject::SetProperty(
@@ -793,7 +793,7 @@
isolate->factory()->NewStringFromAscii(CStrVector("locale")),
isolate->factory()->NewStringFromAscii(CStrVector("und")),
NONE,
- kNonStrictMode);
+ SLOPPY);
}
}
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 38c99e4..48be1d4 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -737,7 +737,7 @@
1 << SharedFunctionInfo::kNativeBitWithinByte);
__ j(not_equal, &shift_arguments);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ mov(ebx, Operand(esp, eax, times_4, 0)); // First argument.
// Call ToObject on the receiver if it is not an object, or use the
@@ -923,7 +923,7 @@
1 << SharedFunctionInfo::kNativeBitWithinByte);
__ j(not_equal, &push_receiver);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
// Call ToObject on the receiver if it is not an object, or use the
// global object if it is null or undefined.
__ JumpIfSmi(ebx, &call_to_object);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index d1725bb..c383ca0 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -1190,7 +1190,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
// esp[0] : return address
// esp[4] : number of parameters
// esp[8] : receiver displacement
@@ -1215,7 +1215,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
Isolate* isolate = masm->isolate();
// esp[0] : return address
@@ -1275,7 +1275,7 @@
__ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize));
// 3. Arguments object.
- __ add(ebx, Immediate(Heap::kArgumentsObjectSize));
+ __ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
__ Allocate(ebx, eax, edx, edi, &runtime, TAG_OBJECT);
@@ -1293,7 +1293,7 @@
__ test(ebx, ebx);
__ j(not_zero, &has_mapped_parameters, Label::kNear);
__ mov(edi, Operand(edi,
- Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX)));
+ Context::SlotOffset(Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX)));
__ jmp(©, Label::kNear);
__ bind(&has_mapped_parameters);
@@ -1330,7 +1330,7 @@
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, edi will point there, otherwise to the
// backing store.
- __ lea(edi, Operand(eax, Heap::kArgumentsObjectSize));
+ __ lea(edi, Operand(eax, Heap::kSloppyArgumentsObjectSize));
__ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
// eax = address of new object (tagged)
@@ -1349,7 +1349,7 @@
__ j(zero, &skip_parameter_map);
__ mov(FieldOperand(edi, FixedArray::kMapOffset),
- Immediate(isolate->factory()->non_strict_arguments_elements_map()));
+ Immediate(isolate->factory()->sloppy_arguments_elements_map()));
__ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2))));
__ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax);
__ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi);
@@ -1475,7 +1475,7 @@
__ j(zero, &add_arguments_object, Label::kNear);
__ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize));
__ bind(&add_arguments_object);
- __ add(ecx, Immediate(Heap::kArgumentsObjectSizeStrict));
+ __ add(ecx, Immediate(Heap::kStrictArgumentsObjectSize));
// Do the allocation of both objects in one go.
__ Allocate(ecx, eax, edx, ebx, &runtime, TAG_OBJECT);
@@ -1484,7 +1484,7 @@
__ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ mov(edi, FieldOperand(edi, GlobalObject::kNativeContextOffset));
const int offset =
- Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
+ Context::SlotOffset(Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX);
__ mov(edi, Operand(edi, offset));
// Copy the JS object part.
@@ -1510,7 +1510,7 @@
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
- __ lea(edi, Operand(eax, Heap::kArgumentsObjectSizeStrict));
+ __ lea(edi, Operand(eax, Heap::kStrictArgumentsObjectSize));
__ mov(FieldOperand(eax, JSObject::kElementsOffset), edi);
__ mov(FieldOperand(edi, FixedArray::kMapOffset),
Immediate(isolate->factory()->fixed_array_map()));
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index 380b15e..54c96fd 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -133,10 +133,10 @@
}
#endif
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
- if (info->is_classic_mode() && !info->is_native()) {
+ if (info->strict_mode() == SLOPPY && !info->is_native()) {
Label ok;
// +1 for return address.
int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
@@ -243,12 +243,12 @@
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
- if (!is_classic_mode()) {
+ if (strict_mode() == STRICT) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (function()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
+ type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
- type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
+ type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
@@ -274,7 +274,7 @@
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableDeclaration* function = scope()->function();
ASSERT(function->proxy()->var()->mode() == CONST ||
- function->proxy()->var()->mode() == CONST_HARMONY);
+ function->proxy()->var()->mode() == CONST_LEGACY);
ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
@@ -744,7 +744,7 @@
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
- bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
+ bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
case Variable::UNALLOCATED:
globals_->Add(variable->name(), zone());
@@ -1260,7 +1260,7 @@
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->language_mode(), info->is_generator());
+ FastNewClosureStub stub(info->strict_mode(), info->is_generator());
__ mov(ebx, Immediate(info));
__ CallStub(&stub);
} else {
@@ -1290,7 +1290,7 @@
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
Immediate(0));
@@ -1304,7 +1304,7 @@
// If no outer scope calls eval, we do not need to check more
// context extensions. If we have reached an eval scope, we check
// all extensions from this point.
- if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
+ if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
s = s->outer_scope();
}
@@ -1349,7 +1349,7 @@
for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ cmp(ContextOperand(context, Context::EXTENSION_INDEX),
Immediate(0));
@@ -1386,14 +1386,13 @@
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == LET ||
- local->mode() == CONST ||
- local->mode() == CONST_HARMONY) {
+ if (local->mode() == LET || local->mode() == CONST ||
+ local->mode() == CONST_LEGACY) {
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, done);
- if (local->mode() == CONST) {
+ if (local->mode() == CONST_LEGACY) {
__ mov(eax, isolate()->factory()->undefined_value());
- } else { // LET || CONST_HARMONY
+ } else { // LET || CONST
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError, 1);
}
@@ -1458,7 +1457,7 @@
// Check that we always have valid source position.
ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
ASSERT(proxy->position() != RelocInfo::kNoPosition);
- skip_init_check = var->mode() != CONST &&
+ skip_init_check = var->mode() != CONST_LEGACY &&
var->initializer_position() < proxy->position();
}
@@ -1468,14 +1467,14 @@
GetVar(eax, var);
__ cmp(eax, isolate()->factory()->the_hole_value());
__ j(not_equal, &done, Label::kNear);
- if (var->mode() == LET || var->mode() == CONST_HARMONY) {
+ if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ push(Immediate(var->name()));
__ CallRuntime(Runtime::kThrowReferenceError, 1);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
- ASSERT(var->mode() == CONST);
+ ASSERT(var->mode() == CONST_LEGACY);
__ mov(eax, isolate()->factory()->undefined_value());
}
__ bind(&done);
@@ -2388,7 +2387,7 @@
__ mov(ecx, eax);
__ pop(edx); // Receiver.
__ pop(eax); // Restore value.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic);
@@ -2411,11 +2410,11 @@
void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, LanguageMode mode) {
+ Handle<String> name, StrictMode strict_mode) {
__ push(eax); // Value.
__ push(esi); // Context.
__ push(Immediate(name));
- __ push(Immediate(Smi::FromInt(mode)));
+ __ push(Immediate(Smi::FromInt(strict_mode)));
__ CallRuntime(Runtime::kStoreContextSlot, 4);
}
@@ -2428,7 +2427,7 @@
__ mov(edx, GlobalObjectOperand());
CallStoreIC();
- } else if (op == Token::INIT_CONST) {
+ } else if (op == Token::INIT_CONST_LEGACY) {
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
@@ -2450,7 +2449,7 @@
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
@@ -2464,11 +2463,11 @@
EmitStoreToStackLocalOrContextSlot(var, location);
}
- } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
+ } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
// Assignment to var or initializing assignment to let/const
// in harmony mode.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
MemOperand location = VarOperand(var, ecx);
@@ -2514,7 +2513,7 @@
__ pop(edx);
// Record source code position before IC call.
SetSourcePosition(expr->position());
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->AssignmentFeedbackId());
@@ -2568,7 +2567,7 @@
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
- // is a classic mode method.
+ // is a sloppy mode method.
__ push(Immediate(isolate()->factory()->undefined_value()));
flags = NO_CALL_FUNCTION_FLAGS;
} else {
@@ -2685,7 +2684,7 @@
// Push the receiver of the enclosing function.
__ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
// Push the language mode.
- __ push(Immediate(Smi::FromInt(language_mode())));
+ __ push(Immediate(Smi::FromInt(strict_mode())));
// Push the start position of the scope the calls resides in.
__ push(Immediate(Smi::FromInt(scope()->start_position())));
@@ -4167,20 +4166,18 @@
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
- __ push(Immediate(Smi::FromInt(strict_mode_flag)));
+ __ push(Immediate(Smi::FromInt(strict_mode())));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(eax);
} else if (proxy != NULL) {
Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
// but "delete this" is allowed.
- ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
+ ASSERT(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
__ push(GlobalObjectOperand());
__ push(Immediate(var->name()));
- __ push(Immediate(Smi::FromInt(kNonStrictMode)));
+ __ push(Immediate(Smi::FromInt(SLOPPY)));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(eax);
} else if (var->IsStackAllocated() || var->IsContextSlot()) {
@@ -4447,7 +4444,7 @@
case KEYED_PROPERTY: {
__ pop(ecx);
__ pop(edx);
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->CountStoreFeedbackId());
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 69f6e3a..c2be7da 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -351,7 +351,7 @@
__ j(not_zero, slow_case);
// Load the elements into scratch1 and check its map.
- Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
+ Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
__ mov(scratch1, FieldOperand(object, JSObject::kElementsOffset));
__ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
@@ -657,7 +657,7 @@
}
-void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ecx : key
// -- edx : receiver
@@ -682,7 +682,7 @@
}
-void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
@@ -859,7 +859,7 @@
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
@@ -1130,7 +1130,7 @@
void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : name
@@ -1151,7 +1151,7 @@
void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 56d850b..024c7ff 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -175,11 +175,11 @@
}
#endif
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
if (info_->this_has_uses() &&
- info_->is_classic_mode() &&
+ info_->strict_mode() == SLOPPY &&
!info_->is_native()) {
Label ok;
// +1 for return address.
@@ -390,6 +390,9 @@
void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
+ if (!instr->IsLazyBailout() && !instr->IsGap()) {
+ safepoints_.BumpLastLazySafepointIndex();
+ }
if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr);
}
@@ -1421,8 +1424,7 @@
// Check for negative zero.
HMod* hmod = instr->hydrogen();
- if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hmod->left()->CanBeNegative()) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ j(not_zero, &remainder_not_zero, Label::kNear);
__ cmp(dividend, Immediate(0));
@@ -1434,8 +1436,6 @@
void LCodeGen::DoModI(LModI* instr) {
HMod* hmod = instr->hydrogen();
- HValue* left = hmod->left();
- HValue* right = hmod->right();
Register left_reg = ToRegister(instr->left());
ASSERT(left_reg.is(eax));
@@ -1448,14 +1448,14 @@
Label done;
// Check for x % 0, idiv would signal a divide error. We have to
// deopt in this case because we can't return a NaN.
- if (right->CanBeZero()) {
+ if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(right_reg, Operand(right_reg));
DeoptimizeIf(zero, instr->environment());
}
// Check for kMinInt % -1, idiv would signal a divide error. We
// have to deopt if we care about -0, because we can't return that.
- if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
+ if (hmod->CheckFlag(HValue::kCanOverflow)) {
Label no_overflow_possible;
__ cmp(left_reg, kMinInt);
__ j(not_equal, &no_overflow_possible, Label::kNear);
@@ -1474,9 +1474,7 @@
__ cdq();
// If we care about -0, test if the dividend is <0 and the result is 0.
- if (left->CanBeNegative() &&
- hmod->CanBeZero() &&
- hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label positive_left;
__ test(left_reg, Operand(left_reg));
__ j(not_sign, &positive_left, Label::kNear);
@@ -1500,14 +1498,12 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr->environment());
}
// Check for (kMinInt / -1).
- if (hdiv->CheckFlag(HValue::kCanOverflow) &&
- hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) {
+ if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmp(dividend, kMinInt);
DeoptimizeIf(zero, instr->environment());
}
@@ -1543,8 +1539,7 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr->environment());
}
@@ -1565,6 +1560,7 @@
void LCodeGen::DoDivI(LDivI* instr) {
+ HBinaryOperation* hdiv = instr->hydrogen();
Register dividend = ToRegister(instr->left());
Register divisor = ToRegister(instr->right());
Register remainder = ToRegister(instr->temp());
@@ -1576,7 +1572,6 @@
ASSERT(!divisor.is(edx));
// Check for x / 0.
- HBinaryOperation* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ test(divisor, divisor);
DeoptimizeIf(zero, instr->environment());
@@ -1606,7 +1601,7 @@
__ cdq();
__ idiv(divisor);
- if (instr->is_flooring()) {
+ if (hdiv->IsMathFloorOfDiv()) {
Label done;
__ test(remainder, remainder);
__ j(zero, &done, Label::kNear);
@@ -1614,8 +1609,7 @@
__ sar(remainder, 31);
__ add(result, remainder);
__ bind(&done);
- } else if (!instr->hydrogen()->CheckFlag(
- HInstruction::kAllUsesTruncatingToInt32)) {
+ } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ test(remainder, remainder);
DeoptimizeIf(not_zero, instr->environment());
@@ -1672,8 +1666,7 @@
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ test(dividend, dividend);
DeoptimizeIf(zero, instr->environment());
}
@@ -2295,7 +2288,6 @@
BinaryOpICStub stub(instr->op(), NO_OVERWRITE);
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
- __ nop(); // Signals no inlined code.
}
@@ -3428,7 +3420,7 @@
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4435,8 +4427,7 @@
ASSERT(ToRegister(instr->value()).is(eax));
__ mov(ecx, instr->name());
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag());
+ Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -4541,7 +4532,7 @@
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4687,7 +4678,7 @@
ASSERT(ToRegister(instr->key()).is(ecx));
ASSERT(ToRegister(instr->value()).is(eax));
- Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+ Handle<Code> ic = instr->strict_mode() == STRICT
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
@@ -5998,7 +5989,7 @@
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(instr->hydrogen()->language_mode(),
+ FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
instr->hydrogen()->is_generator());
__ mov(ebx, Immediate(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h
index c5e253b..079595c 100644
--- a/src/ia32/lithium-codegen-ia32.h
+++ b/src/ia32/lithium-codegen-ia32.h
@@ -179,9 +179,7 @@
#undef DECLARE_DO
private:
- StrictModeFlag strict_mode_flag() const {
- return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
- }
+ StrictMode strict_mode() const { return info()->strict_mode(); }
Scope* scope() const { return scope_; }
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index c4ad7e8..896b499 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -679,15 +679,6 @@
instr->MarkAsCall();
instr = AssignPointerMap(instr);
- if (hinstr->HasObservableSideEffects()) {
- ASSERT(hinstr->next()->IsSimulate());
- HSimulate* sim = HSimulate::cast(hinstr->next());
- ASSERT(instruction_pending_deoptimization_environment_ == NULL);
- ASSERT(pending_deoptimization_ast_id_.IsNone());
- instruction_pending_deoptimization_environment_ = instr;
- pending_deoptimization_ast_id_ = sim->ast_id();
- }
-
// If instruction does not have side-effects lazy deoptimization
// after the call will try to deoptimize to the point before the call.
// Thus we still need to attach environment to this call even if
@@ -980,6 +971,26 @@
chunk_->AddInstruction(clobber, current_block_);
}
chunk_->AddInstruction(instr, current_block_);
+
+ if (instr->IsCall()) {
+ HValue* hydrogen_value_for_lazy_bailout = current;
+ LInstruction* instruction_needing_environment = NULL;
+ if (current->HasObservableSideEffects()) {
+ HSimulate* sim = HSimulate::cast(current->next());
+ instruction_needing_environment = instr;
+ sim->ReplayEnvironment(current_block_->last_environment());
+ hydrogen_value_for_lazy_bailout = sim;
+ }
+ LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
+ bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
+ chunk_->AddInstruction(bailout, current_block_);
+ if (instruction_needing_environment != NULL) {
+ // Store the lazy deopt environment with the instruction if needed.
+ // Right now it is only used for LInstanceOfKnownGlobal.
+ instruction_needing_environment->
+ SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
+ }
+ }
}
current_instruction_ = old_current;
}
@@ -1327,16 +1338,15 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor));
- bool can_deopt =
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- (instr->CheckFlag(HValue::kCanOverflow) &&
- instr->left()->RangeCanInclude(kMinInt) && divisor == -1) ||
+ LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
+ dividend, divisor));
+ if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
(!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
- divisor != 1 && divisor != -1);
- return can_deopt ? AssignEnvironment(result) : result;
+ divisor != 1 && divisor != -1)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1348,15 +1358,14 @@
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp1 = FixedTemp(eax);
LOperand* temp2 = FixedTemp(edx);
- LInstruction* result =
- DefineFixed(
- new(zone()) LDivByConstI(dividend, divisor, temp1, temp2), edx);
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineFixed(new(zone()) LDivByConstI(
+ dividend, divisor, temp1, temp2), edx);
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1367,9 +1376,16 @@
LOperand* dividend = UseFixed(instr->left(), eax);
LOperand* divisor = UseRegister(instr->right());
LOperand* temp = FixedTemp(edx);
- LInstruction* result =
- DefineFixed(new(zone()) LDivI(dividend, divisor, temp), eax);
- return AssignEnvironment(result);
+ LInstruction* result = DefineFixed(new(zone()) LDivI(
+ dividend, divisor, temp), eax);
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+ instr->CheckFlag(HValue::kCanOverflow) ||
+ (!instr->IsMathFloorOfDiv() &&
+ !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1418,8 +1434,7 @@
edx);
bool can_deopt =
divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0);
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
return can_deopt ? AssignEnvironment(result) : result;
}
@@ -1441,12 +1456,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegisterAtStart(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
- bool can_deopt =
- instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative();
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
+ dividend, divisor));
+ if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1458,14 +1473,12 @@
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp1 = FixedTemp(eax);
LOperand* temp2 = FixedTemp(edx);
- LInstruction* result =
- DefineFixed(
- new(zone()) LModByConstI(dividend, divisor, temp1, temp2), eax);
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative());
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineFixed(new(zone()) LModByConstI(
+ dividend, divisor, temp1, temp2), eax);
+ if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1476,16 +1489,13 @@
LOperand* dividend = UseFixed(instr->left(), eax);
LOperand* divisor = UseRegister(instr->right());
LOperand* temp = FixedTemp(edx);
- LInstruction* result =
- DefineFixed(new(zone()) LModI(dividend, divisor, temp), edx);
- bool can_deopt = (instr->right()->CanBeZero() ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(kMinInt) &&
- instr->right()->RangeCanInclude(-1)) ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative() &&
- instr->CanBeZero()));
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineFixed(new(zone()) LModI(
+ dividend, divisor, temp), edx);
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -2586,22 +2596,6 @@
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
instr->ReplayEnvironment(current_block_->last_environment());
-
- // If there is an instruction pending deoptimization environment create a
- // lazy bailout instruction to capture the environment.
- if (!pending_deoptimization_ast_id_.IsNone()) {
- ASSERT(pending_deoptimization_ast_id_ == instr->ast_id());
- LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
- LInstruction* result = AssignEnvironment(lazy_bailout);
- // Store the lazy deopt environment with the instruction if needed. Right
- // now it is only used for LInstanceOfKnownGlobal.
- instruction_pending_deoptimization_environment_->
- SetDeferredLazyDeoptimizationEnvironment(result->environment());
- instruction_pending_deoptimization_environment_ = NULL;
- pending_deoptimization_ast_id_ = BailoutId::None();
- return result;
- }
-
return NULL;
}
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index ac9cffa..5770ff6 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -756,8 +756,6 @@
LOperand* right() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
- bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
-
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
};
@@ -2241,7 +2239,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2298,7 +2296,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2754,9 +2752,7 @@
current_instruction_(NULL),
current_block_(NULL),
next_block_(NULL),
- allocator_(allocator),
- instruction_pending_deoptimization_environment_(NULL),
- pending_deoptimization_ast_id_(BailoutId::None()) { }
+ allocator_(allocator) { }
// Build the sequence for the graph.
LPlatformChunk* Build();
@@ -2908,8 +2904,6 @@
HBasicBlock* current_block_;
HBasicBlock* next_block_;
LAllocator* allocator_;
- LInstruction* instruction_pending_deoptimization_environment_;
- BailoutId pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 2e5b835..eef2edd 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -2833,6 +2833,15 @@
}
+void MacroAssembler::Move(Register dst, Immediate imm) {
+ if (imm.is_zero()) {
+ xor_(dst, dst);
+ } else {
+ mov(dst, imm);
+ }
+}
+
+
void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
if (FLAG_native_code_counters && counter->Enabled()) {
mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index dafa65d..7f393c9 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -843,6 +843,9 @@
// Move if the registers are not identical.
void Move(Register target, Register source);
+ // Move a constant into a register using the most efficient encoding.
+ void Move(Register dst, Immediate imm);
+
// Push a handle value.
void Push(Handle<Object> handle) { push(Immediate(handle)); }
void Push(Smi* smi) { Push(Handle<Smi>(smi, isolate())); }
diff --git a/src/ic.cc b/src/ic.cc
index 3b54b9c..a70ac1c 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -943,8 +943,8 @@
Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
if (!object->IsJSObject() &&
!function->IsBuiltin() &&
- function->shared()->is_classic_mode()) {
- // Calling non-strict non-builtins with a value as the receiver
+ function->shared()->strict_mode() == SLOPPY) {
+ // Calling sloppy non-builtins with a value as the receiver
// requires boxing.
break;
}
@@ -1078,12 +1078,12 @@
} else if (object->IsJSObject()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (receiver->elements()->map() ==
- isolate()->heap()->non_strict_arguments_elements_map()) {
- stub = non_strict_arguments_stub();
+ isolate()->heap()->sloppy_arguments_elements_map()) {
+ stub = sloppy_arguments_stub();
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
} else if (!key->ToSmi()->IsFailure() &&
- (!target().is_identical_to(non_strict_arguments_stub()))) {
+ (!target().is_identical_to(sloppy_arguments_stub()))) {
stub = LoadElementStub(receiver);
}
}
@@ -1182,7 +1182,7 @@
}
// The length property of string values is read-only. Throw in strict mode.
- if (strict_mode() == kStrictMode && object->IsString() &&
+ if (strict_mode() == STRICT && object->IsString() &&
name->Equals(isolate()->heap()->length_string())) {
return TypeError("strict_read_only_property", object, name);
}
@@ -1233,7 +1233,7 @@
LookupResult lookup(isolate());
bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
if (!can_store &&
- strict_mode() == kStrictMode &&
+ strict_mode() == STRICT &&
!(lookup.IsProperty() && lookup.IsReadOnly()) &&
object->IsGlobalObject()) {
// Strict mode doesn't allow setting non-existent global property.
@@ -1263,7 +1263,7 @@
Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ExtraICState extra_state = ComputeExtraICState(strict_mode);
Handle<Code> ic = isolate->stub_cache()->ComputeStore(
UNINITIALIZED, extra_state);
@@ -1282,7 +1282,7 @@
Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ExtraICState state = ComputeExtraICState(strict_mode);
return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state);
}
@@ -1316,7 +1316,7 @@
Handle<JSObject> holder(lookup->holder());
// Handlers do not use strict mode.
- StoreStubCompiler compiler(isolate(), kNonStrictMode, kind());
+ StoreStubCompiler compiler(isolate(), SLOPPY, kind());
switch (lookup->type()) {
case FIELD:
return compiler.CompileStoreField(receiver, lookup, name);
@@ -1687,12 +1687,12 @@
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
if (receiver->elements()->map() ==
- isolate()->heap()->non_strict_arguments_elements_map()) {
- if (strict_mode() == kNonStrictMode) {
- stub = non_strict_arguments_stub();
+ isolate()->heap()->sloppy_arguments_elements_map()) {
+ if (strict_mode() == SLOPPY) {
+ stub = sloppy_arguments_stub();
}
} else if (key_is_smi_like &&
- !(target().is_identical_to(non_strict_arguments_stub()))) {
+ !(target().is_identical_to(sloppy_arguments_stub()))) {
// We should go generic if receiver isn't a dictionary, but our
// prototype chain does have dictionary elements. This ensures that
// other non-dictionary receivers in the polymorphic case benefit
@@ -1899,7 +1899,7 @@
Handle<Object> object = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1);
Handle<Object> value = args.at<Object>(2);
- StrictModeFlag strict_mode = ic.strict_mode();
+ StrictMode strict_mode = ic.strict_mode();
Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
value,
NONE,
@@ -1916,7 +1916,7 @@
Handle<Object> object = args.at<Object>(0);
Handle<Object> key = args.at<Object>(1);
Handle<Object> value = args.at<Object>(2);
- StrictModeFlag strict_mode = ic.strict_mode();
+ StrictMode strict_mode = ic.strict_mode();
Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
value,
NONE,
@@ -1934,7 +1934,7 @@
Handle<Map> map = args.at<Map>(1);
Handle<Object> key = args.at<Object>(2);
Handle<Object> object = args.at<Object>(3);
- StrictModeFlag strict_mode = ic.strict_mode();
+ StrictMode strict_mode = ic.strict_mode();
if (object->IsJSObject()) {
JSObject::TransitionElementsKind(Handle<JSObject>::cast(object),
map->elements_kind());
diff --git a/src/ic.h b/src/ic.h
index 213a481..ec9fe8b 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -399,7 +399,7 @@
static void GenerateGeneric(MacroAssembler* masm);
static void GenerateString(MacroAssembler* masm);
static void GenerateIndexedInterceptor(MacroAssembler* masm);
- static void GenerateNonStrictArguments(MacroAssembler* masm);
+ static void GenerateSloppyArguments(MacroAssembler* masm);
// Bit mask to be tested against bit field for the cases when
// generic stub should go into slow case.
@@ -436,8 +436,8 @@
Handle<Code> indexed_interceptor_stub() {
return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
}
- Handle<Code> non_strict_arguments_stub() {
- return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
+ Handle<Code> sloppy_arguments_stub() {
+ return isolate()->builtins()->KeyedLoadIC_SloppyArguments();
}
Handle<Code> string_stub() {
return isolate()->builtins()->KeyedLoadIC_String();
@@ -451,12 +451,11 @@
class StoreIC: public IC {
public:
- class StrictModeState: public BitField<StrictModeFlag, 1, 1> {};
- static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
+ class StrictModeState: public BitField<StrictMode, 1, 1> {};
+ static ExtraICState ComputeExtraICState(StrictMode flag) {
return StrictModeState::encode(flag);
}
-
- static StrictModeFlag GetStrictMode(ExtraICState state) {
+ static StrictMode GetStrictMode(ExtraICState state) {
return StrictModeState::decode(state);
}
@@ -470,7 +469,7 @@
ASSERT(IsStoreStub());
}
- StrictModeFlag strict_mode() const {
+ StrictMode strict_mode() const {
return StrictModeState::decode(extra_ic_state());
}
@@ -484,10 +483,10 @@
static void GenerateMegamorphic(MacroAssembler* masm);
static void GenerateNormal(MacroAssembler* masm);
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Code> initialize_stub(Isolate* isolate,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
MUST_USE_RESULT MaybeObject* Store(
Handle<Object> object,
@@ -512,7 +511,7 @@
}
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
// Update the inline cache and the global stub cache based on the
// lookup result.
@@ -559,7 +558,7 @@
class ExtraICStateKeyedAccessStoreMode:
public BitField<KeyedAccessStoreMode, 2, 4> {}; // NOLINT
- static ExtraICState ComputeExtraICState(StrictModeFlag flag,
+ static ExtraICState ComputeExtraICState(StrictMode flag,
KeyedAccessStoreMode mode) {
return StrictModeState::encode(flag) |
ExtraICStateKeyedAccessStoreMode::encode(mode);
@@ -587,9 +586,9 @@
static void GenerateMiss(MacroAssembler* masm);
static void GenerateSlow(MacroAssembler* masm);
static void GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode);
- static void GenerateGeneric(MacroAssembler* masm, StrictModeFlag strict_mode);
- static void GenerateNonStrictArguments(MacroAssembler* masm);
+ StrictMode strict_mode);
+ static void GenerateGeneric(MacroAssembler* masm, StrictMode strict_mode);
+ static void GenerateSloppyArguments(MacroAssembler* masm);
protected:
virtual Code::Kind kind() const { return Code::KEYED_STORE_IC; }
@@ -600,8 +599,8 @@
return pre_monomorphic_stub(isolate(), strict_mode());
}
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
- StrictModeFlag strict_mode) {
- if (strict_mode == kStrictMode) {
+ StrictMode strict_mode) {
+ if (strict_mode == STRICT) {
return isolate->builtins()->KeyedStoreIC_PreMonomorphic_Strict();
} else {
return isolate->builtins()->KeyedStoreIC_PreMonomorphic();
@@ -611,7 +610,7 @@
return isolate()->builtins()->KeyedStoreIC_Slow();
}
virtual Handle<Code> megamorphic_stub() {
- if (strict_mode() == kStrictMode) {
+ if (strict_mode() == STRICT) {
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
} else {
return isolate()->builtins()->KeyedStoreIC_Generic();
@@ -630,15 +629,15 @@
// Stub accessors.
virtual Handle<Code> generic_stub() const {
- if (strict_mode() == kStrictMode) {
+ if (strict_mode() == STRICT) {
return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
} else {
return isolate()->builtins()->KeyedStoreIC_Generic();
}
}
- Handle<Code> non_strict_arguments_stub() {
- return isolate()->builtins()->KeyedStoreIC_NonStrictArguments();
+ Handle<Code> sloppy_arguments_stub() {
+ return isolate()->builtins()->KeyedStoreIC_SloppyArguments();
}
static void Clear(Isolate* isolate, Address address, Code* target);
diff --git a/src/isolate.cc b/src/isolate.cc
index 8c1c2c1..bb97c93 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -453,10 +453,10 @@
// If the caller parameter is a function we skip frames until we're
// under it before starting to collect.
bool seen_caller = !caller->IsJSFunction();
- // First element is reserved to store the number of non-strict frames.
+ // First element is reserved to store the number of sloppy frames.
int cursor = 1;
int frames_seen = 0;
- int non_strict_frames = 0;
+ int sloppy_frames = 0;
bool encountered_strict_function = false;
for (StackFrameIterator iter(this);
!iter.done() && frames_seen < limit;
@@ -487,13 +487,13 @@
Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this);
// The stack trace API should not expose receivers and function
// objects on frames deeper than the top-most one with a strict
- // mode function. The number of non-strict frames is stored as
+ // mode function. The number of sloppy frames is stored as
// first element in the result array.
if (!encountered_strict_function) {
- if (!fun->shared()->is_classic_mode()) {
+ if (fun->shared()->strict_mode() == STRICT) {
encountered_strict_function = true;
} else {
- non_strict_frames++;
+ sloppy_frames++;
}
}
elements->set(cursor++, *recv);
@@ -503,7 +503,7 @@
}
}
}
- elements->set(0, Smi::FromInt(non_strict_frames));
+ elements->set(0, Smi::FromInt(sloppy_frames));
Handle<JSArray> result = factory()->NewJSArrayWithElements(elements);
result->set_length(Smi::FromInt(cursor));
return result;
diff --git a/src/json-parser.h b/src/json-parser.h
index c164ebf..0973589 100644
--- a/src/json-parser.h
+++ b/src/json-parser.h
@@ -361,7 +361,7 @@
Handle<Object> value = ParseJsonValue();
if (value.is_null()) return ReportUnexpectedCharacter();
- JSObject::SetOwnElement(json_object, index, value, kNonStrictMode);
+ JSObject::SetOwnElement(json_object, index, value, SLOPPY);
continue;
}
// Not an index, fallback to the slow path.
diff --git a/src/liveedit.cc b/src/liveedit.cc
index 5da91ad..91f8150 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -49,14 +49,14 @@
#ifdef ENABLE_DEBUGGER_SUPPORT
-void SetElementNonStrict(Handle<JSObject> object,
- uint32_t index,
- Handle<Object> value) {
+void SetElementSloppy(Handle<JSObject> object,
+ uint32_t index,
+ Handle<Object> value) {
// Ignore return value from SetElement. It can only be a failure if there
// are element setters causing exceptions and the debugger context has none
// of these.
Handle<Object> no_failure =
- JSObject::SetElement(object, index, value, NONE, kNonStrictMode);
+ JSObject::SetElement(object, index, value, NONE, SLOPPY);
ASSERT(!no_failure.is_null());
USE(no_failure);
}
@@ -359,17 +359,17 @@
void WriteChunk(int char_pos1, int char_pos2, int char_len1, int char_len2) {
Isolate* isolate = array_->GetIsolate();
- SetElementNonStrict(array_,
- current_size_,
- Handle<Object>(Smi::FromInt(char_pos1), isolate));
- SetElementNonStrict(array_,
- current_size_ + 1,
- Handle<Object>(Smi::FromInt(char_pos1 + char_len1),
- isolate));
- SetElementNonStrict(array_,
- current_size_ + 2,
- Handle<Object>(Smi::FromInt(char_pos2 + char_len2),
- isolate));
+ SetElementSloppy(array_,
+ current_size_,
+ Handle<Object>(Smi::FromInt(char_pos1), isolate));
+ SetElementSloppy(array_,
+ current_size_ + 1,
+ Handle<Object>(Smi::FromInt(char_pos1 + char_len1),
+ isolate));
+ SetElementSloppy(array_,
+ current_size_ + 2,
+ Handle<Object>(Smi::FromInt(char_pos2 + char_len2),
+ isolate));
current_size_ += 3;
}
@@ -662,12 +662,12 @@
protected:
void SetField(int field_position, Handle<Object> value) {
- SetElementNonStrict(array_, field_position, value);
+ SetElementSloppy(array_, field_position, value);
}
void SetSmiValueField(int field_position, int value) {
- SetElementNonStrict(array_,
- field_position,
- Handle<Smi>(Smi::FromInt(value), isolate()));
+ SetElementSloppy(array_,
+ field_position,
+ Handle<Smi>(Smi::FromInt(value), isolate()));
}
Object* GetField(int field_position) {
return array_->GetElementNoExceptionThrown(isolate(), field_position);
@@ -818,7 +818,7 @@
fun->materialized_literal_count(),
current_parent_index_);
current_parent_index_ = len_;
- SetElementNonStrict(result_, len_, info.GetJSArray());
+ SetElementSloppy(result_, len_, info.GetJSArray());
len_++;
}
@@ -885,20 +885,20 @@
context_list.Sort(&Variable::CompareIndex);
for (int i = 0; i < context_list.length(); i++) {
- SetElementNonStrict(scope_info_list,
- scope_info_length,
- context_list[i]->name());
+ SetElementSloppy(scope_info_list,
+ scope_info_length,
+ context_list[i]->name());
scope_info_length++;
- SetElementNonStrict(
+ SetElementSloppy(
scope_info_list,
scope_info_length,
Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate()));
scope_info_length++;
}
- SetElementNonStrict(scope_info_list,
- scope_info_length,
- Handle<Object>(isolate()->heap()->null_value(),
- isolate()));
+ SetElementSloppy(scope_info_list,
+ scope_info_length,
+ Handle<Object>(isolate()->heap()->null_value(),
+ isolate()));
scope_info_length++;
current_scope = current_scope->outer_scope();
@@ -959,11 +959,11 @@
Handle<Smi> end_pos(Smi::FromInt(message_location.end_pos()), isolate);
Handle<JSValue> script_obj = GetScriptWrapper(message_location.script());
JSReceiver::SetProperty(
- rethrow_exception, start_pos_key, start_pos, NONE, kNonStrictMode);
+ rethrow_exception, start_pos_key, start_pos, NONE, SLOPPY);
JSReceiver::SetProperty(
- rethrow_exception, end_pos_key, end_pos, NONE, kNonStrictMode);
+ rethrow_exception, end_pos_key, end_pos, NONE, SLOPPY);
JSReceiver::SetProperty(
- rethrow_exception, script_obj_key, script_obj, NONE, kNonStrictMode);
+ rethrow_exception, script_obj_key, script_obj, NONE, SLOPPY);
}
}
@@ -992,7 +992,7 @@
Handle<String> name_handle(String::cast(info->name()));
info_wrapper.SetProperties(name_handle, info->start_position(),
info->end_position(), info);
- SetElementNonStrict(array, i, info_wrapper.GetJSArray());
+ SetElementSloppy(array, i, info_wrapper.GetJSArray());
}
}
@@ -1639,8 +1639,7 @@
UnwrapSharedFunctionInfoFromJSValue(jsvalue);
if (function->shared() == *shared || IsInlined(*function, *shared)) {
- SetElementNonStrict(result, i, Handle<Smi>(Smi::FromInt(status),
- isolate));
+ SetElementSloppy(result, i, Handle<Smi>(Smi::FromInt(status), isolate));
return true;
}
}
@@ -1954,7 +1953,7 @@
Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
Handle<Object> replaced(
Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
- SetElementNonStrict(result, i, replaced);
+ SetElementSloppy(result, i, replaced);
}
}
return NULL;
@@ -1995,7 +1994,7 @@
// Fill the default values.
for (int i = 0; i < len; i++) {
- SetElementNonStrict(
+ SetElementSloppy(
result,
i,
Handle<Smi>(Smi::FromInt(FUNCTION_AVAILABLE_FOR_PATCH), isolate));
@@ -2018,7 +2017,7 @@
// Add error message as an array extra element.
Vector<const char> vector_message(error_message, StrLength(error_message));
Handle<String> str = isolate->factory()->NewStringFromAscii(vector_message);
- SetElementNonStrict(result, len, str);
+ SetElementSloppy(result, len, str);
}
return result;
}
diff --git a/src/messages.js b/src/messages.js
index ca2da30..fbe9151 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -155,8 +155,8 @@
invalid_preparser_data: ["Invalid preparser data for function ", "%0"],
strict_mode_with: ["Strict mode code may not include a with statement"],
strict_eval_arguments: ["Unexpected eval or arguments in strict mode"],
- too_many_arguments: ["Too many arguments in function call (only 32766 allowed)"],
- too_many_parameters: ["Too many parameters in function definition (only 32766 allowed)"],
+ too_many_arguments: ["Too many arguments in function call (only 65535 allowed)"],
+ too_many_parameters: ["Too many parameters in function definition (only 65535 allowed)"],
too_many_variables: ["Too many variables declared (only 131071 allowed)"],
strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
strict_octal_literal: ["Octal literals are not allowed in strict mode."],
@@ -1074,15 +1074,15 @@
function GetStackFrames(raw_stack) {
var frames = new InternalArray();
- var non_strict_frames = raw_stack[0];
+ var sloppy_frames = raw_stack[0];
for (var i = 1; i < raw_stack.length; i += 4) {
var recv = raw_stack[i];
var fun = raw_stack[i + 1];
var code = raw_stack[i + 2];
var pc = raw_stack[i + 3];
var pos = %FunctionGetPositionForOffset(code, pc);
- non_strict_frames--;
- frames.push(new CallSite(recv, fun, pos, (non_strict_frames < 0)));
+ sloppy_frames--;
+ frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0)));
}
return frames;
}
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 9f18f4e..b0a70a2 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -1066,7 +1066,7 @@
__ And(t3, a3, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
__ Branch(&shift_arguments, ne, t3, Operand(zero_reg));
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
// Load first argument in a2. a2 = -kPointerSize(sp + n_args << 2).
__ sll(at, a0, kPointerSizeLog2);
__ addu(a2, sp, at);
@@ -1269,7 +1269,7 @@
__ And(t3, a2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize)));
__ Branch(&push_receiver, ne, t3, Operand(zero_reg));
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ JumpIfSmi(a0, &call_to_object);
__ LoadRoot(a1, Heap::kNullValueRootIndex);
__ Branch(&use_global_receiver, eq, a0, Operand(a1));
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 8941519..dc8ff6e 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -2365,7 +2365,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
// sp[0] : number of parameters
// sp[4] : receiver displacement
// sp[8] : function
@@ -2391,7 +2391,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// Stack layout:
// sp[0] : number of parameters (tagged)
// sp[4] : address of receiver argument
@@ -2455,7 +2455,7 @@
__ Addu(t5, t5, Operand(FixedArray::kHeaderSize));
// 3. Arguments object.
- __ Addu(t5, t5, Operand(Heap::kArgumentsObjectSize));
+ __ Addu(t5, t5, Operand(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
__ Allocate(t5, v0, a3, t0, &runtime, TAG_OBJECT);
@@ -2464,7 +2464,7 @@
// a2 = argument count (tagged)
// Get the arguments boilerplate from the current native context into t0.
const int kNormalOffset =
- Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX);
+ Context::SlotOffset(Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX);
const int kAliasedOffset =
Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX);
@@ -2505,7 +2505,7 @@
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, t0 will point there, otherwise
// it will point to the backing store.
- __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSize));
+ __ Addu(t0, v0, Operand(Heap::kSloppyArgumentsObjectSize));
__ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
// v0 = address of new object (tagged)
@@ -2523,7 +2523,7 @@
__ Branch(&skip_parameter_map, eq, a1, Operand(Smi::FromInt(0)));
- __ LoadRoot(t2, Heap::kNonStrictArgumentsElementsMapRootIndex);
+ __ LoadRoot(t2, Heap::kSloppyArgumentsElementsMapRootIndex);
__ sw(t2, FieldMemOperand(t0, FixedArray::kMapOffset));
__ Addu(t2, a1, Operand(Smi::FromInt(2)));
__ sw(t2, FieldMemOperand(t0, FixedArray::kLengthOffset));
@@ -2646,7 +2646,7 @@
__ Addu(a1, a1, Operand(FixedArray::kHeaderSize / kPointerSize));
__ bind(&add_arguments_object);
- __ Addu(a1, a1, Operand(Heap::kArgumentsObjectSizeStrict / kPointerSize));
+ __ Addu(a1, a1, Operand(Heap::kStrictArgumentsObjectSize / kPointerSize));
// Do the allocation of both objects in one go.
__ Allocate(a1, v0, a2, a3, &runtime,
@@ -2656,7 +2656,7 @@
__ lw(t0, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ lw(t0, FieldMemOperand(t0, GlobalObject::kNativeContextOffset));
__ lw(t0, MemOperand(t0, Context::SlotOffset(
- Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX)));
+ Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX)));
// Copy the JS object part.
__ CopyFields(v0, t0, a3.bit(), JSObject::kHeaderSize / kPointerSize);
@@ -2675,7 +2675,7 @@
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
- __ Addu(t0, v0, Operand(Heap::kArgumentsObjectSizeStrict));
+ __ Addu(t0, v0, Operand(Heap::kStrictArgumentsObjectSize));
__ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset));
__ LoadRoot(a3, Heap::kFixedArrayMapRootIndex);
__ sw(a3, FieldMemOperand(t0, FixedArray::kMapOffset));
@@ -3285,7 +3285,7 @@
__ Branch(&cont, ne, at, Operand(zero_reg));
}
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ lw(a3, MemOperand(sp, argc_ * kPointerSize));
if (NeedsChecks()) {
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 9eec0a3..8250ce0 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -153,10 +153,10 @@
}
#endif
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
- if (info->is_classic_mode() && !info->is_native()) {
+ if (info->strict_mode() == SLOPPY && !info->is_native()) {
Label ok;
int receiver_offset = info->scope()->num_parameters() * kPointerSize;
__ lw(at, MemOperand(sp, receiver_offset));
@@ -271,12 +271,12 @@
// The stub will rewrite receiever and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
- if (!is_classic_mode()) {
+ if (strict_mode() == STRICT) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (function()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
+ type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
- type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
+ type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
@@ -302,7 +302,7 @@
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableDeclaration* function = scope()->function();
ASSERT(function->proxy()->var()->mode() == CONST ||
- function->proxy()->var()->mode() == CONST_HARMONY);
+ function->proxy()->var()->mode() == CONST_LEGACY);
ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
@@ -803,7 +803,7 @@
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
- bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
+ bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
case Variable::UNALLOCATED:
globals_->Add(variable->name(), zone());
@@ -1336,7 +1336,7 @@
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->language_mode(), info->is_generator());
+ FastNewClosureStub stub(info->strict_mode(), info->is_generator());
__ li(a2, Operand(info));
__ CallStub(&stub);
} else {
@@ -1366,7 +1366,7 @@
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ lw(temp, ContextOperand(current, Context::EXTENSION_INDEX));
__ Branch(slow, ne, temp, Operand(zero_reg));
@@ -1378,7 +1378,7 @@
}
// If no outer scope calls eval, we do not need to check more
// context extensions.
- if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
+ if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
s = s->outer_scope();
}
@@ -1419,7 +1419,7 @@
for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ lw(temp, ContextOperand(context, Context::EXTENSION_INDEX));
__ Branch(slow, ne, temp, Operand(zero_reg));
@@ -1455,15 +1455,14 @@
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ lw(v0, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == LET ||
- local->mode() == CONST ||
- local->mode() == CONST_HARMONY) {
+ if (local->mode() == LET || local->mode() == CONST ||
+ local->mode() == CONST_LEGACY) {
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ subu(at, v0, at); // Sub as compare: at == 0 on eq.
- if (local->mode() == CONST) {
+ if (local->mode() == CONST_LEGACY) {
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole.
- } else { // LET || CONST_HARMONY
+ } else { // LET || CONST
__ Branch(done, ne, at, Operand(zero_reg));
__ li(a0, Operand(var->name()));
__ push(a0);
@@ -1530,7 +1529,7 @@
// Check that we always have valid source position.
ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
ASSERT(proxy->position() != RelocInfo::kNoPosition);
- skip_init_check = var->mode() != CONST &&
+ skip_init_check = var->mode() != CONST_LEGACY &&
var->initializer_position() < proxy->position();
}
@@ -1539,7 +1538,7 @@
GetVar(v0, var);
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ subu(at, v0, at); // Sub as compare: at == 0 on eq.
- if (var->mode() == LET || var->mode() == CONST_HARMONY) {
+ if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
Label done;
@@ -1550,7 +1549,7 @@
__ bind(&done);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
- ASSERT(var->mode() == CONST);
+ ASSERT(var->mode() == CONST_LEGACY);
__ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
__ Movz(v0, a0, at); // Conditional move: Undefined if TheHole.
}
@@ -2459,7 +2458,7 @@
VisitForAccumulatorValue(prop->key());
__ mov(a1, result_register());
__ Pop(a0, a2); // a0 = restored value.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic);
@@ -2484,16 +2483,15 @@
void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, LanguageMode mode) {
+ Handle<String> name, StrictMode strict_mode) {
__ li(a1, Operand(name));
- __ li(a0, Operand(Smi::FromInt(mode)));
+ __ li(a0, Operand(Smi::FromInt(strict_mode)));
__ Push(v0, cp, a1, a0); // Value, context, name, strict mode.
__ CallRuntime(Runtime::kStoreContextSlot, 4);
}
-void FullCodeGenerator::EmitVariableAssignment(Variable* var,
- Token::Value op) {
+void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(a0, result_register());
@@ -2501,7 +2499,7 @@
__ lw(a1, GlobalObjectOperand());
CallStoreIC();
- } else if (op == Token::INIT_CONST) {
+ } else if (op == Token::INIT_CONST_LEGACY) {
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
@@ -2522,7 +2520,7 @@
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
@@ -2538,11 +2536,11 @@
EmitStoreToStackLocalOrContextSlot(var, location);
}
- } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
+ } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
// Assignment to var or initializing assignment to let/const
// in harmony mode.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT((var->IsStackAllocated() || var->IsContextSlot()));
MemOperand location = VarOperand(var, a1);
@@ -2591,7 +2589,7 @@
__ mov(a0, result_register());
__ Pop(a2, a1); // a1 = key.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->AssignmentFeedbackId());
@@ -2641,7 +2639,7 @@
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
- // is a classic mode method.
+ // is a sloppy mode method.
__ Push(isolate()->factory()->undefined_value());
flags = NO_CALL_FUNCTION_FLAGS;
} else {
@@ -2757,8 +2755,8 @@
int receiver_offset = 2 + info_->scope()->num_parameters();
__ lw(t1, MemOperand(fp, receiver_offset * kPointerSize));
- // t0: the language mode.
- __ li(t0, Operand(Smi::FromInt(language_mode())));
+ // t0: the strict mode.
+ __ li(t0, Operand(Smi::FromInt(strict_mode())));
// a1: the start position of the scope the calls resides in.
__ li(a1, Operand(Smi::FromInt(scope()->start_position())));
@@ -4227,9 +4225,7 @@
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
- __ li(a1, Operand(Smi::FromInt(strict_mode_flag)));
+ __ li(a1, Operand(Smi::FromInt(strict_mode())));
__ push(a1);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(v0);
@@ -4237,11 +4233,11 @@
Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
// but "delete this" is allowed.
- ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
+ ASSERT(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
__ lw(a2, GlobalObjectOperand());
__ li(a1, Operand(var->name()));
- __ li(a0, Operand(Smi::FromInt(kNonStrictMode)));
+ __ li(a0, Operand(Smi::FromInt(SLOPPY)));
__ Push(a2, a1, a0);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(v0);
@@ -4500,7 +4496,7 @@
case KEYED_PROPERTY: {
__ mov(a0, result_register()); // Value.
__ Pop(a2, a1); // a1 = key, a2 = receiver.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->CountStoreFeedbackId());
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 4088ea4..09ffe95 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -417,6 +417,8 @@
Register scratch3,
Label* unmapped_case,
Label* slow_case) {
+ Heap* heap = masm->isolate()->heap();
+
// Check that the receiver is a JSObject. Because of the map check
// later, we do not need to check for interceptors or whether it
// requires access checks.
@@ -430,10 +432,11 @@
__ Branch(slow_case, ne, scratch1, Operand(zero_reg));
// Load the elements into scratch1 and check its map.
+ Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
__ lw(scratch1, FieldMemOperand(object, JSObject::kElementsOffset));
__ CheckMap(scratch1,
scratch2,
- Heap::kNonStrictArgumentsElementsMapRootIndex,
+ arguments_map,
slow_case,
DONT_DO_SMI_CHECK);
// Check if element is in the range of mapped arguments. If not, jump
@@ -496,7 +499,7 @@
}
-void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- lr : return address
// -- a0 : key
@@ -521,7 +524,7 @@
}
-void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ---------- S t a t e --------------
// -- a0 : value
// -- a1 : key
@@ -800,7 +803,7 @@
void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ---------- S t a t e --------------
// -- a0 : value
// -- a1 : key
@@ -992,7 +995,7 @@
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ---------- S t a t e --------------
// -- a0 : value
// -- a1 : key
@@ -1235,7 +1238,7 @@
void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- a0 : value
// -- a1 : receiver
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index b5102a4..292ce13 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -146,11 +146,11 @@
// fp: Caller's frame pointer.
// lr: Caller's pc.
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
if (info_->this_has_uses() &&
- info_->is_classic_mode() &&
+ info_->strict_mode() == SLOPPY &&
!info_->is_native()) {
Label ok;
int receiver_offset = info_->scope()->num_parameters() * kPointerSize;
@@ -259,6 +259,13 @@
}
+void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
+ if (!instr->IsLazyBailout() && !instr->IsGap()) {
+ safepoints_.BumpLastLazySafepointIndex();
+ }
+}
+
+
bool LCodeGen::GenerateDeferredCode() {
ASSERT(is_generating());
if (deferred_.length() > 0) {
@@ -1095,8 +1102,6 @@
void LCodeGen::DoModI(LModI* instr) {
HMod* hmod = instr->hydrogen();
- HValue* left = hmod->left();
- HValue* right = hmod->right();
const Register left_reg = ToRegister(instr->left());
const Register right_reg = ToRegister(instr->right());
const Register result_reg = ToRegister(instr->result());
@@ -1107,24 +1112,28 @@
Label done;
// Check for x % 0, we have to deopt in this case because we can't return a
// NaN.
- if (right->CanBeZero()) {
+ if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg));
}
- // Check for kMinInt % -1, we have to deopt if we care about -0, because we
- // can't return that.
- if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
- Label left_not_min_int;
- __ Branch(&left_not_min_int, ne, left_reg, Operand(kMinInt));
- // TODO(svenpanne) Don't deopt when we don't care about -0.
- DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1));
- __ bind(&left_not_min_int);
+ // Check for kMinInt % -1, div will return kMinInt, which is not what we
+ // want. We have to deopt if we care about -0, because we can't return that.
+ if (hmod->CheckFlag(HValue::kCanOverflow)) {
+ Label no_overflow_possible;
+ __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1));
+ } else {
+ __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
+ __ Branch(USE_DELAY_SLOT, &done);
+ __ mov(result_reg, zero_reg);
+ }
+ __ bind(&no_overflow_possible);
}
- // TODO(svenpanne) Only emit the test/deopt if we have to.
+ // If we care about -0, test if the dividend is <0 and the result is 0.
__ Branch(USE_DELAY_SLOT, &done, ge, left_reg, Operand(zero_reg));
__ mfhi(result_reg);
-
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg));
}
@@ -1133,6 +1142,7 @@
void LCodeGen::DoDivI(LDivI* instr) {
+ HBinaryOperation* hdiv = instr->hydrogen();
const Register left = ToRegister(instr->left());
const Register right = ToRegister(instr->right());
const Register result = ToRegister(instr->result());
@@ -1142,12 +1152,12 @@
__ div(left, right);
// Check for x / 0.
- if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
+ if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
DeoptimizeIf(eq, instr->environment(), right, Operand(zero_reg));
}
// Check for (0 / -x) that will produce negative zero.
- if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label left_not_zero;
__ Branch(&left_not_zero, ne, left, Operand(zero_reg));
DeoptimizeIf(lt, instr->environment(), right, Operand(zero_reg));
@@ -1155,14 +1165,15 @@
}
// Check for (kMinInt / -1).
- if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
+ if (hdiv->CheckFlag(HValue::kCanOverflow) &&
+ !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
Label left_not_min_int;
__ Branch(&left_not_min_int, ne, left, Operand(kMinInt));
DeoptimizeIf(eq, instr->environment(), right, Operand(-1));
__ bind(&left_not_min_int);
}
- if (!instr->hydrogen()->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
__ mfhi(result);
DeoptimizeIf(ne, instr->environment(), result, Operand(zero_reg));
}
@@ -1233,8 +1244,7 @@
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg));
}
@@ -3028,7 +3038,7 @@
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4004,8 +4014,7 @@
// Name is always in a2.
__ li(a2, Operand(instr->name()));
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag());
+ Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -4136,7 +4145,7 @@
case FAST_HOLEY_ELEMENTS:
case FAST_HOLEY_SMI_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4261,7 +4270,7 @@
ASSERT(ToRegister(instr->key()).is(a1));
ASSERT(ToRegister(instr->value()).is(a0));
- Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+ Handle<Code> ic = (instr->strict_mode() == STRICT)
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
@@ -5322,7 +5331,7 @@
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(instr->hydrogen()->language_mode(),
+ FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
instr->hydrogen()->is_generator());
__ li(a2, Operand(instr->hydrogen()->shared_info()));
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
diff --git a/src/mips/lithium-codegen-mips.h b/src/mips/lithium-codegen-mips.h
index 28782cc..63f0661 100644
--- a/src/mips/lithium-codegen-mips.h
+++ b/src/mips/lithium-codegen-mips.h
@@ -163,9 +163,7 @@
#undef DECLARE_DO
private:
- StrictModeFlag strict_mode_flag() const {
- return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
- }
+ StrictMode strict_mode() const { return info()->strict_mode(); }
Scope* scope() const { return scope_; }
@@ -193,6 +191,7 @@
// Code generation passes. Returns true if code generation should
// continue.
+ void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE;
bool GeneratePrologue();
bool GenerateDeferredCode();
bool GenerateDeoptJumpTable();
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index d2cc39b..93acbab 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -619,15 +619,6 @@
instr->MarkAsCall();
instr = AssignPointerMap(instr);
- if (hinstr->HasObservableSideEffects()) {
- ASSERT(hinstr->next()->IsSimulate());
- HSimulate* sim = HSimulate::cast(hinstr->next());
- ASSERT(instruction_pending_deoptimization_environment_ == NULL);
- ASSERT(pending_deoptimization_ast_id_.IsNone());
- instruction_pending_deoptimization_environment_ = instr;
- pending_deoptimization_ast_id_ = sim->ast_id();
- }
-
// If instruction does not have side-effects lazy deoptimization
// after the call will try to deoptimize to the point before the call.
// Thus we still need to attach environment to this call even if
@@ -913,6 +904,26 @@
instr = AssignEnvironment(instr);
}
chunk_->AddInstruction(instr, current_block_);
+
+ if (instr->IsCall()) {
+ HValue* hydrogen_value_for_lazy_bailout = current;
+ LInstruction* instruction_needing_environment = NULL;
+ if (current->HasObservableSideEffects()) {
+ HSimulate* sim = HSimulate::cast(current->next());
+ instruction_needing_environment = instr;
+ sim->ReplayEnvironment(current_block_->last_environment());
+ hydrogen_value_for_lazy_bailout = sim;
+ }
+ LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
+ bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
+ chunk_->AddInstruction(bailout, current_block_);
+ if (instruction_needing_environment != NULL) {
+ // Store the lazy deopt environment with the instruction if needed.
+ // Right now it is only used for LInstanceOfKnownGlobal.
+ instruction_needing_environment->
+ SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
+ }
+ }
}
current_instruction_ = old_current;
}
@@ -1289,8 +1300,7 @@
DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
bool can_deopt =
divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0);
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
return can_deopt ? AssignEnvironment(result) : result;
}
@@ -1317,12 +1327,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegisterAtStart(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
- bool can_deopt =
- instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative();
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
+ dividend, divisor));
+ if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1332,17 +1342,13 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
LOperand* divisor = UseRegister(instr->right());
- LModI* mod = new(zone()) LModI(dividend,
- divisor);
- LInstruction* result = DefineAsRegister(mod);
- bool can_deopt = (instr->right()->CanBeZero() ||
- (instr->left()->RangeCanInclude(kMinInt) &&
- instr->right()->RangeCanInclude(-1) &&
- instr->CheckFlag(HValue::kBailoutOnMinusZero)) ||
- (instr->left()->CanBeNegative() &&
- instr->CanBeZero() &&
- instr->CheckFlag(HValue::kBailoutOnMinusZero)));
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineAsRegister(new(zone()) LModI(
+ dividend, divisor));
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -2352,21 +2358,6 @@
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
instr->ReplayEnvironment(current_block_->last_environment());
-
- // If there is an instruction pending deoptimization environment create a
- // lazy bailout instruction to capture the environment.
- if (pending_deoptimization_ast_id_ == instr->ast_id()) {
- LInstruction* result = new(zone()) LLazyBailout;
- result = AssignEnvironment(result);
- // Store the lazy deopt environment with the instruction if needed. Right
- // now it is only used for LInstanceOfKnownGlobal.
- instruction_pending_deoptimization_environment_->
- SetDeferredLazyDeoptimizationEnvironment(result->environment());
- instruction_pending_deoptimization_environment_ = NULL;
- pending_deoptimization_ast_id_ = BailoutId::None();
- return result;
- }
-
return NULL;
}
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index 45b6cb5..b778517 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -2141,7 +2141,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2198,7 +2198,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2642,9 +2642,7 @@
current_instruction_(NULL),
current_block_(NULL),
next_block_(NULL),
- allocator_(allocator),
- instruction_pending_deoptimization_environment_(NULL),
- pending_deoptimization_ast_id_(BailoutId::None()) { }
+ allocator_(allocator) { }
// Build the sequence for the graph.
LPlatformChunk* Build();
@@ -2784,8 +2782,6 @@
HBasicBlock* current_block_;
HBasicBlock* next_block_;
LAllocator* allocator_;
- LInstruction* instruction_pending_deoptimization_environment_;
- BailoutId pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};
diff --git a/src/objects-debug.cc b/src/objects-debug.cc
index 0988d9d..4fafc15 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -275,7 +275,7 @@
VerifyHeapPointer(properties());
VerifyHeapPointer(elements());
- if (GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) {
+ if (GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS) {
CHECK(this->elements()->IsFixedArray());
CHECK_GE(this->elements()->length(), 2);
}
@@ -1060,7 +1060,7 @@
dict->Capacity() - dict->NumberOfElements();
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
break;
}
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index ec2ffdb..6c5b4bf 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1739,7 +1739,7 @@
SeededNumberDictionary* dictionary;
MaybeObject* maybe = SeededNumberDictionary::Allocate(GetHeap(), 0);
if (!maybe->To(&dictionary)) return maybe;
- if (map() == GetHeap()->non_strict_arguments_elements_map()) {
+ if (map() == GetHeap()->sloppy_arguments_elements_map()) {
FixedArray::cast(elements())->set(1, dictionary);
} else {
set_elements(dictionary);
@@ -5146,39 +5146,21 @@
}
-LanguageMode SharedFunctionInfo::language_mode() {
- int hints = compiler_hints();
- if (BooleanBit::get(hints, kExtendedModeFunction)) {
- ASSERT(BooleanBit::get(hints, kStrictModeFunction));
- return EXTENDED_MODE;
- }
- return BooleanBit::get(hints, kStrictModeFunction)
- ? STRICT_MODE : CLASSIC_MODE;
+StrictMode SharedFunctionInfo::strict_mode() {
+ return BooleanBit::get(compiler_hints(), kStrictModeFunction)
+ ? STRICT : SLOPPY;
}
-void SharedFunctionInfo::set_language_mode(LanguageMode language_mode) {
- // We only allow language mode transitions that go set the same language mode
- // again or go up in the chain:
- // CLASSIC_MODE -> STRICT_MODE -> EXTENDED_MODE.
- ASSERT(this->language_mode() == CLASSIC_MODE ||
- this->language_mode() == language_mode ||
- language_mode == EXTENDED_MODE);
+void SharedFunctionInfo::set_strict_mode(StrictMode strict_mode) {
+ // We only allow mode transitions from sloppy to strict.
+ ASSERT(this->strict_mode() == SLOPPY || this->strict_mode() == strict_mode);
int hints = compiler_hints();
- hints = BooleanBit::set(
- hints, kStrictModeFunction, language_mode != CLASSIC_MODE);
- hints = BooleanBit::set(
- hints, kExtendedModeFunction, language_mode == EXTENDED_MODE);
+ hints = BooleanBit::set(hints, kStrictModeFunction, strict_mode == STRICT);
set_compiler_hints(hints);
}
-bool SharedFunctionInfo::is_classic_mode() {
- return !BooleanBit::get(compiler_hints(), kStrictModeFunction);
-}
-
-BOOL_GETTER(SharedFunctionInfo, compiler_hints, is_extended_mode,
- kExtendedModeFunction)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative)
BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, inline_builtin,
kInlineBuiltin)
@@ -5448,6 +5430,11 @@
bool was_optimized = IsOptimized();
bool is_optimized = code->kind() == Code::OPTIMIZED_FUNCTION;
+ if (was_optimized && is_optimized) {
+ shared()->EvictFromOptimizedCodeMap(this->code(),
+ "Replacing with another optimized code");
+ }
+
set_code(code);
// Add/remove the function from the list of optimized functions for this
@@ -5704,6 +5691,7 @@
WRITE_FIELD(this, kRelocationInfoOffset, NULL);
WRITE_FIELD(this, kHandlerTableOffset, NULL);
WRITE_FIELD(this, kDeoptimizationDataOffset, NULL);
+ WRITE_FIELD(this, kConstantPoolOffset, NULL);
// Do not wipe out e.g. a minor key.
if (!READ_FIELD(this, kTypeFeedbackInfoOffset)->IsSmi()) {
WRITE_FIELD(this, kTypeFeedbackInfoOffset, NULL);
@@ -5925,7 +5913,7 @@
fixed_array->IsFixedArray() &&
fixed_array->IsDictionary()) ||
(kind > DICTIONARY_ELEMENTS));
- ASSERT((kind != NON_STRICT_ARGUMENTS_ELEMENTS) ||
+ ASSERT((kind != SLOPPY_ARGUMENTS_ELEMENTS) ||
(elements()->IsFixedArray() && elements()->length() >= 2));
}
#endif
@@ -5973,8 +5961,8 @@
}
-bool JSObject::HasNonStrictArgumentsElements() {
- return GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS;
+bool JSObject::HasSloppyArgumentsElements() {
+ return GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS;
}
diff --git a/src/objects-printer.cc b/src/objects-printer.cc
index 15ea33a..e287691 100644
--- a/src/objects-printer.cc
+++ b/src/objects-printer.cc
@@ -378,7 +378,7 @@
case DICTIONARY_ELEMENTS:
elements()->Print(out);
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
FixedArray* p = FixedArray::cast(elements());
PrintF(out, " parameter map:");
for (int i = 2; i < p->length(); i++) {
diff --git a/src/objects.cc b/src/objects.cc
index aebcc01..ec8493a 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -519,7 +519,7 @@
Handle<JSReceiver> receiver,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
Isolate* isolate = proxy->GetIsolate();
Handle<String> name = isolate->factory()->Uint32ToString(index);
return SetPropertyWithHandler(
@@ -2147,7 +2147,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
JSReceiver::StoreFromKeyed store_mode,
ExtensibilityCheck extensibility_check,
ValueType value_type,
@@ -2163,7 +2163,7 @@
if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
!object->map()->is_extensible()) {
- if (strict_mode == kNonStrictMode) {
+ if (strict_mode == SLOPPY) {
return value;
} else {
Handle<Object> args[1] = { name };
@@ -2236,7 +2236,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// Check local property, ignore interceptor.
LookupResult result(object->GetIsolate());
object->LocalLookupRealNamedProperty(*name, &result);
@@ -2846,7 +2846,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// TODO(rossberg): Support symbols in the API.
if (name->IsSymbol()) return value;
Isolate* isolate = object->GetIsolate();
@@ -2878,7 +2878,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_mode) {
LookupResult result(object->GetIsolate());
object->LocalLookup(*name, &result, true);
@@ -2895,7 +2895,7 @@
Handle<Name> name,
Handle<Object> value,
Handle<JSObject> holder,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
Isolate* isolate = object->GetIsolate();
// We should never get here to initialize a const with the hole
@@ -2954,9 +2954,7 @@
return SetPropertyWithDefinedSetter(
object, Handle<JSReceiver>::cast(setter), value);
} else {
- if (strict_mode == kNonStrictMode) {
- return value;
- }
+ if (strict_mode == SLOPPY) return value;
Handle<Object> args[2] = { name, holder };
Handle<Object> error =
isolate->factory()->NewTypeError("no_setter_in_callback",
@@ -3007,7 +3005,7 @@
uint32_t index,
Handle<Object> value,
bool* found,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
Isolate *isolate = object->GetIsolate();
for (Handle<Object> proto = handle(object->GetPrototype(), isolate);
!proto->IsNull();
@@ -3047,7 +3045,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool* done) {
Isolate* isolate = object->GetIsolate();
@@ -3091,7 +3089,7 @@
// If we get here with *done true, we have encountered a read-only property.
if (*done) {
- if (strict_mode == kNonStrictMode) return value;
+ if (strict_mode == SLOPPY) return value;
Handle<Object> args[] = { name, object };
Handle<Object> error = isolate->factory()->NewTypeError(
"strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
@@ -3460,7 +3458,7 @@
Handle<Name> name,
Handle<Object> value,
bool check_prototype,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
if (check_prototype && !result->IsProperty()) {
object->LookupRealNamedPropertyInPrototypes(*name, result);
}
@@ -3527,7 +3525,7 @@
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_mode) {
if (result->IsHandler()) {
return JSProxy::SetPropertyWithHandler(handle(result->proxy()),
@@ -3559,7 +3557,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
Isolate* isolate = proxy->GetIsolate();
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
@@ -3579,7 +3577,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool* done) {
Isolate* isolate = proxy->GetIsolate();
Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy.
@@ -3647,7 +3645,7 @@
ASSERT(writable->IsTrue() || writable->IsFalse());
*done = writable->IsFalse();
if (!*done) return isolate->factory()->the_hole_value();
- if (strict_mode == kNonStrictMode) return value;
+ if (strict_mode == SLOPPY) return value;
Handle<Object> args[] = { name, receiver };
Handle<Object> error = isolate->factory()->NewTypeError(
"strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
@@ -3666,7 +3664,7 @@
receiver, Handle<JSReceiver>::cast(setter), value);
}
- if (strict_mode == kNonStrictMode) return value;
+ if (strict_mode == SLOPPY) return value;
Handle<Object> args2[] = { name, proxy };
Handle<Object> error = isolate->factory()->NewTypeError(
"no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
@@ -3916,7 +3914,7 @@
// of the map. If we get a fast copy of the map, all field representations
// will be tagged since the transition is omitted.
return JSObject::AddProperty(
- object, name, value, attributes, kNonStrictMode,
+ object, name, value, attributes, SLOPPY,
JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
JSReceiver::OMIT_EXTENSIBILITY_CHECK,
JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
@@ -4028,7 +4026,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_mode) {
Isolate* isolate = object->GetIsolate();
@@ -4077,7 +4075,7 @@
}
if (lookup->IsProperty() && lookup->IsReadOnly()) {
- if (strict_mode == kStrictMode) {
+ if (strict_mode == STRICT) {
Handle<Object> args[] = { name, object };
Handle<Object> error = isolate->factory()->NewTypeError(
"strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
@@ -4183,7 +4181,7 @@
if (object->IsAccessCheckNeeded()) {
if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) {
return SetPropertyWithFailedAccessCheck(object, &lookup, name, value,
- false, kNonStrictMode);
+ false, SLOPPY);
}
}
@@ -4206,7 +4204,7 @@
TransitionFlag flag = lookup.IsFound()
? OMIT_TRANSITION : INSERT_TRANSITION;
// Neither properties nor transitions found.
- return AddProperty(object, name, value, attributes, kNonStrictMode,
+ return AddProperty(object, name, value, attributes, SLOPPY,
MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag);
}
@@ -4736,7 +4734,7 @@
FixedArrayBase* array = FixedArrayBase::cast(elements());
Map* old_map = array->map();
bool is_arguments =
- (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
+ (old_map == old_map->GetHeap()->sloppy_arguments_elements_map());
if (is_arguments) {
array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
}
@@ -5389,7 +5387,7 @@
if (ReferencesObjectFromElements(elements, kind, obj)) return true;
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
FixedArray* parameter_map = FixedArray::cast(elements());
// Check the mapped parameters.
int length = parameter_map->length();
@@ -5411,7 +5409,7 @@
// Get the constructor function for arguments array.
JSObject* arguments_boilerplate =
heap->isolate()->context()->native_context()->
- arguments_boilerplate();
+ sloppy_arguments_boilerplate();
JSFunction* arguments_function =
JSFunction::cast(arguments_boilerplate->map()->constructor());
@@ -5533,8 +5531,8 @@
Handle<Object> JSObject::Freeze(Handle<JSObject> object) {
- // Freezing non-strict arguments should be handled elsewhere.
- ASSERT(!object->HasNonStrictArgumentsElements());
+ // Freezing sloppy arguments should be handled elsewhere.
+ ASSERT(!object->HasSloppyArgumentsElements());
ASSERT(!object->map()->is_observed());
if (object->map()->is_frozen()) return object;
@@ -5801,7 +5799,7 @@
if (copying) {
// Creating object copy for literals. No strict mode needed.
CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty(
- copy, key_string, result, NONE, kNonStrictMode));
+ copy, key_string, result, NONE, SLOPPY));
}
}
}
@@ -5860,7 +5858,7 @@
}
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNIMPLEMENTED();
break;
@@ -5918,9 +5916,9 @@
JSObject* curr = JSObject::cast(o);
int enum_length = curr->map()->EnumLength();
if (enum_length == kInvalidEnumCacheSentinel) return false;
+ if (curr->IsAccessCheckNeeded()) return false;
ASSERT(!curr->HasNamedInterceptor());
ASSERT(!curr->HasIndexedInterceptor());
- ASSERT(!curr->IsAccessCheckNeeded());
if (curr->NumberOfEnumElements() > 0) return false;
if (curr != this && enum_length != 0) return false;
}
@@ -6121,7 +6119,7 @@
return;
}
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
// Ascertain whether we have read-only properties or an existing
// getter/setter pair in an arguments elements dictionary backing
// store.
@@ -6273,7 +6271,7 @@
dictionary->set_requires_slow_elements();
// Update the dictionary backing store on the object.
- if (object->elements()->map() == heap->non_strict_arguments_elements_map()) {
+ if (object->elements()->map() == heap->sloppy_arguments_elements_map()) {
// Also delete any parameter alias.
//
// TODO(kmillikin): when deleting the last parameter alias we could
@@ -6575,7 +6573,7 @@
case DICTIONARY_ELEMENTS:
break;
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNIMPLEMENTED();
break;
}
@@ -9811,15 +9809,15 @@
void JSFunction::RemovePrototype() {
Context* native_context = context()->native_context();
- Map* no_prototype_map = shared()->is_classic_mode()
- ? native_context->function_without_prototype_map()
- : native_context->strict_mode_function_without_prototype_map();
+ Map* no_prototype_map = shared()->strict_mode() == SLOPPY
+ ? native_context->sloppy_function_without_prototype_map()
+ : native_context->strict_function_without_prototype_map();
if (map() == no_prototype_map) return;
- ASSERT(map() == (shared()->is_classic_mode()
- ? native_context->function_map()
- : native_context->strict_mode_function_map()));
+ ASSERT(map() == (shared()->strict_mode() == SLOPPY
+ ? native_context->sloppy_function_map()
+ : native_context->strict_function_map()));
set_map(no_prototype_map);
set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
@@ -11078,9 +11076,7 @@
switch (kind) {
case STORE_IC:
case KEYED_STORE_IC:
- if (extra == kStrictMode) {
- name = "STRICT";
- }
+ if (extra == STRICT) name = "STRICT";
break;
default:
break;
@@ -11247,7 +11243,7 @@
accessor->CopyElements(this, new_elements, elements_kind);
if (maybe_obj->IsFailure()) return maybe_obj;
- if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
+ if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
Map* new_map = map();
if (new_elements_kind != elements_kind) {
MaybeObject* maybe =
@@ -11319,7 +11315,7 @@
accessor->CopyElements(this, elems, elements_kind);
if (maybe_obj->IsFailure()) return maybe_obj;
}
- if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
+ if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) {
ValidateElements();
set_map_and_elements(new_map, elems);
} else {
@@ -11490,12 +11486,12 @@
if (delete_count > 0) {
for (int i = indices.length() - 1; i >= 0; i--) {
JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE,
- kNonStrictMode);
+ SLOPPY);
}
SetProperty(deleted, isolate->factory()->length_string(),
isolate->factory()->NewNumberFromUint(delete_count),
- NONE, kNonStrictMode);
+ NONE, SLOPPY);
}
EnqueueSpliceRecord(self, index, deleted, add_count);
@@ -11934,7 +11930,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode) {
Isolate* isolate = object->GetIsolate();
@@ -12022,7 +12018,7 @@
uint32_t index,
Handle<Object> value,
Handle<JSObject> holder,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
Isolate* isolate = object->GetIsolate();
// We should never get here to initialize a const with the hole
@@ -12061,9 +12057,7 @@
return SetPropertyWithDefinedSetter(
object, Handle<JSReceiver>::cast(setter), value);
} else {
- if (strict_mode == kNonStrictMode) {
- return value;
- }
+ if (strict_mode == SLOPPY) return value;
Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
Handle<Object> args[2] = { key, holder };
Handle<Object> error = isolate->factory()->NewTypeError(
@@ -12085,7 +12079,7 @@
Heap* heap = GetHeap();
if (!elements()->IsFixedArray()) return false;
FixedArray* elements = FixedArray::cast(this->elements());
- if (elements->map() != heap->non_strict_arguments_elements_map()) {
+ if (elements->map() != heap->sloppy_arguments_elements_map()) {
return false;
}
FixedArray* arguments = FixedArray::cast(elements->get(1));
@@ -12097,7 +12091,7 @@
Heap* heap = GetHeap();
if (!elements()->IsFixedArray()) return false;
FixedArray* elements = FixedArray::cast(this->elements());
- if (elements->map() != heap->non_strict_arguments_elements_map()) {
+ if (elements->map() != heap->sloppy_arguments_elements_map()) {
return false;
}
FixedArray* arguments = FixedArray::cast(elements->get(1));
@@ -12111,7 +12105,7 @@
Handle<Object> JSObject::SetFastElement(Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype) {
ASSERT(object->HasFastSmiOrObjectElements() ||
object->HasFastArgumentsElements());
@@ -12129,7 +12123,7 @@
Handle<FixedArray> backing_store(FixedArray::cast(object->elements()));
if (backing_store->map() ==
- isolate->heap()->non_strict_arguments_elements_map()) {
+ isolate->heap()->sloppy_arguments_elements_map()) {
backing_store = handle(FixedArray::cast(backing_store->get(1)));
} else {
backing_store = EnsureWritableFastElements(object);
@@ -12240,7 +12234,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode) {
ASSERT(object->HasDictionaryElements() ||
@@ -12250,7 +12244,7 @@
// Insert element in the dictionary.
Handle<FixedArray> elements(FixedArray::cast(object->elements()));
bool is_arguments =
- (elements->map() == isolate->heap()->non_strict_arguments_elements_map());
+ (elements->map() == isolate->heap()->sloppy_arguments_elements_map());
Handle<SeededNumberDictionary> dictionary(is_arguments
? SeededNumberDictionary::cast(elements->get(1))
: SeededNumberDictionary::cast(*elements));
@@ -12272,7 +12266,7 @@
attributes, NORMAL, details.dictionary_index());
dictionary->DetailsAtPut(entry, details);
} else if (details.IsReadOnly() && !element->IsTheHole()) {
- if (strict_mode == kNonStrictMode) {
+ if (strict_mode == SLOPPY) {
return isolate->factory()->undefined_value();
} else {
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
@@ -12310,7 +12304,7 @@
// When we set the is_extensible flag to false we always force the
// element into dictionary mode (and force them to stay there).
if (!object->map()->is_extensible()) {
- if (strict_mode == kNonStrictMode) {
+ if (strict_mode == SLOPPY) {
return isolate->factory()->undefined_value();
} else {
Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
@@ -12383,7 +12377,7 @@
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype) {
ASSERT(object->HasFastDoubleElements());
@@ -12481,7 +12475,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
if (object->IsJSProxy()) {
return JSProxy::SetElementWithHandler(
Handle<JSProxy>::cast(object), object, index, value, strict_mode);
@@ -12494,7 +12488,7 @@
Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ASSERT(!object->HasExternalArrayElements());
return JSObject::SetElement(object, index, value, NONE, strict_mode, false);
}
@@ -12504,7 +12498,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode) {
Isolate* isolate = object->GetIsolate();
@@ -12637,7 +12631,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode) {
ASSERT(object->HasDictionaryElements() ||
@@ -12685,7 +12679,7 @@
return SetDictionaryElement(object, index, value, attributes, strict_mode,
check_prototype,
set_mode);
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
uint32_t length = parameter_map->length();
Handle<Object> probe = index < length - 2 ?
@@ -13044,7 +13038,7 @@
FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
FixedArray* backing_store = NULL;
switch (GetElementsKind()) {
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
backing_store_base =
FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
backing_store = FixedArray::cast(backing_store_base);
@@ -13160,7 +13154,7 @@
FixedArray* elements = FixedArray::cast(this->elements());
SeededNumberDictionary* dictionary = NULL;
- if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
+ if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) {
dictionary = SeededNumberDictionary::cast(elements->get(1));
} else {
dictionary = SeededNumberDictionary::cast(elements);
@@ -13640,7 +13634,7 @@
counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS: {
+ case SLOPPY_ARGUMENTS_ELEMENTS: {
FixedArray* parameter_map = FixedArray::cast(elements());
int mapped_length = parameter_map->length() - 2;
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
@@ -13738,11 +13732,11 @@
public:
StringSharedKey(String* source,
SharedFunctionInfo* shared,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position)
: source_(source),
shared_(shared),
- language_mode_(language_mode),
+ strict_mode_(strict_mode),
scope_position_(scope_position) { }
bool IsMatch(Object* other) {
@@ -13750,12 +13744,10 @@
FixedArray* other_array = FixedArray::cast(other);
SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
if (shared != shared_) return false;
- int language_unchecked = Smi::cast(other_array->get(2))->value();
- ASSERT(language_unchecked == CLASSIC_MODE ||
- language_unchecked == STRICT_MODE ||
- language_unchecked == EXTENDED_MODE);
- LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
- if (language_mode != language_mode_) return false;
+ int strict_unchecked = Smi::cast(other_array->get(2))->value();
+ ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
+ StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
+ if (strict_mode != strict_mode_) return false;
int scope_position = Smi::cast(other_array->get(3))->value();
if (scope_position != scope_position_) return false;
String* source = String::cast(other_array->get(1));
@@ -13764,7 +13756,7 @@
static uint32_t StringSharedHashHelper(String* source,
SharedFunctionInfo* shared,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position) {
uint32_t hash = source->Hash();
if (shared->HasSourceCode()) {
@@ -13775,8 +13767,7 @@
// collection.
Script* script = Script::cast(shared->script());
hash ^= String::cast(script->source())->Hash();
- if (language_mode == STRICT_MODE) hash ^= 0x8000;
- if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
+ if (strict_mode == STRICT) hash ^= 0x8000;
hash += scope_position;
}
return hash;
@@ -13784,21 +13775,19 @@
uint32_t Hash() {
return StringSharedHashHelper(
- source_, shared_, language_mode_, scope_position_);
+ source_, shared_, strict_mode_, scope_position_);
}
uint32_t HashForObject(Object* obj) {
FixedArray* other_array = FixedArray::cast(obj);
SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
String* source = String::cast(other_array->get(1));
- int language_unchecked = Smi::cast(other_array->get(2))->value();
- ASSERT(language_unchecked == CLASSIC_MODE ||
- language_unchecked == STRICT_MODE ||
- language_unchecked == EXTENDED_MODE);
- LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
+ int strict_unchecked = Smi::cast(other_array->get(2))->value();
+ ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT);
+ StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked);
int scope_position = Smi::cast(other_array->get(3))->value();
return StringSharedHashHelper(
- source, shared, language_mode, scope_position);
+ source, shared, strict_mode, scope_position);
}
MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
@@ -13809,7 +13798,7 @@
FixedArray* other_array = FixedArray::cast(obj);
other_array->set(0, shared_);
other_array->set(1, source_);
- other_array->set(2, Smi::FromInt(language_mode_));
+ other_array->set(2, Smi::FromInt(strict_mode_));
other_array->set(3, Smi::FromInt(scope_position_));
return other_array;
}
@@ -13817,7 +13806,7 @@
private:
String* source_;
SharedFunctionInfo* shared_;
- LanguageMode language_mode_;
+ StrictMode strict_mode_;
int scope_position_;
};
@@ -15010,22 +14999,11 @@
}
-// The key for the script compilation cache is dependent on the mode flags,
-// because they change the global language mode and thus binding behaviour.
-// If flags change at some point, we must ensure that we do not hit the cache
-// for code compiled with different settings.
-static LanguageMode CurrentGlobalLanguageMode() {
- return FLAG_use_strict
- ? (FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE)
- : CLASSIC_MODE;
-}
-
-
Object* CompilationCacheTable::Lookup(String* src, Context* context) {
SharedFunctionInfo* shared = context->closure()->shared();
StringSharedKey key(src,
shared,
- CurrentGlobalLanguageMode(),
+ FLAG_use_strict ? STRICT : SLOPPY,
RelocInfo::kNoPosition);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
@@ -15035,11 +15013,11 @@
Object* CompilationCacheTable::LookupEval(String* src,
Context* context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position) {
StringSharedKey key(src,
context->closure()->shared(),
- language_mode,
+ strict_mode,
scope_position);
int entry = FindEntry(&key);
if (entry == kNotFound) return GetHeap()->undefined_value();
@@ -15062,7 +15040,7 @@
SharedFunctionInfo* shared = context->closure()->shared();
StringSharedKey key(src,
shared,
- CurrentGlobalLanguageMode(),
+ FLAG_use_strict ? STRICT : SLOPPY,
RelocInfo::kNoPosition);
CompilationCacheTable* cache;
MaybeObject* maybe_cache = EnsureCapacity(1, &key);
@@ -15086,7 +15064,7 @@
int scope_position) {
StringSharedKey key(src,
context->closure()->shared(),
- value->language_mode(),
+ value->strict_mode(),
scope_position);
Object* obj;
{ MaybeObject* maybe_obj = EnsureCapacity(1, &key);
diff --git a/src/objects.h b/src/objects.h
index cd8999c..dcb2721 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -2043,14 +2043,14 @@
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_mode =
MAY_BE_STORE_FROM_KEYED);
static Handle<Object> SetElement(Handle<JSReceiver> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
// Implementation of [[HasProperty]], ECMA-262 5th edition, section 8.12.6.
static inline bool HasProperty(Handle<JSReceiver> object, Handle<Name> name);
@@ -2123,7 +2123,7 @@
Handle<Name> key,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_from_keyed);
DISALLOW_IMPLICIT_CONSTRUCTORS(JSReceiver);
@@ -2155,14 +2155,14 @@
// In the fast mode elements is a FixedArray and so each element can
// be quickly accessed. This fact is used in the generated code. The
// elements array can have one of three maps in this mode:
- // fixed_array_map, non_strict_arguments_elements_map or
+ // fixed_array_map, sloppy_arguments_elements_map or
// fixed_cow_array_map (for copy-on-write arrays). In the latter case
// the elements array may be shared by a few objects and so before
// writing to any element the array must be copied. Use
// EnsureWritableFastElements in this case.
//
// In the slow mode the elements is either a NumberDictionary, an
- // ExternalArray, or a FixedArray parameter map for a (non-strict)
+ // ExternalArray, or a FixedArray parameter map for a (sloppy)
// arguments object.
DECL_ACCESSORS(elements, FixedArrayBase)
inline void initialize_elements();
@@ -2184,7 +2184,7 @@
// Returns true if an object has elements of FAST_HOLEY_*_ELEMENTS
// ElementsKind.
inline bool HasFastHoleyElements();
- inline bool HasNonStrictArgumentsElements();
+ inline bool HasSloppyArgumentsElements();
inline bool HasDictionaryElements();
inline bool HasExternalUint8ClampedElements();
@@ -2236,14 +2236,14 @@
Handle<Name> name,
Handle<Object> value,
Handle<JSObject> holder,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> SetPropertyWithInterceptor(
Handle<JSObject> object,
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> SetPropertyForResult(
Handle<JSObject> object,
@@ -2251,7 +2251,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED);
static Handle<Object> SetLocalPropertyIgnoreAttributes(
@@ -2436,13 +2436,13 @@
static Handle<Object> SetFastElement(Handle<JSObject> object, uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype);
static Handle<Object> SetOwnElement(Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
// Empty handle is returned if the element cannot be set to the given value.
static Handle<Object> SetElement(
@@ -2450,7 +2450,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype = true,
SetPropertyMode set_mode = SET_PROPERTY);
@@ -2771,13 +2771,13 @@
uint32_t index,
Handle<Object> value,
Handle<JSObject> holder,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> SetElementWithInterceptor(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode);
static Handle<Object> SetElementWithoutInterceptor(
@@ -2785,7 +2785,7 @@
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode);
static Handle<Object> SetElementWithCallbackSetterInPrototypes(
@@ -2793,20 +2793,20 @@
uint32_t index,
Handle<Object> value,
bool* found,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> SetDictionaryElement(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype,
SetPropertyMode set_mode = SET_PROPERTY);
static Handle<Object> SetFastDoubleElement(
Handle<JSObject> object,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool check_prototype = true);
// Searches the prototype chain for property 'name'. If it is found and
@@ -2818,14 +2818,14 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool* done);
static Handle<Object> SetPropertyPostInterceptor(
Handle<JSObject> object,
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> SetPropertyUsingTransition(
Handle<JSObject> object,
LookupResult* lookup,
@@ -2838,7 +2838,7 @@
Handle<Name> name,
Handle<Object> value,
bool check_prototype,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
// Add a property to an object.
static Handle<Object> AddProperty(
@@ -2846,7 +2846,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
StoreFromKeyed store_mode = MAY_BE_STORE_FROM_KEYED,
ExtensibilityCheck extensibility_check = PERFORM_EXTENSIBILITY_CHECK,
ValueType value_type = OPTIMAL_REPRESENTATION,
@@ -4339,13 +4339,11 @@
// Does this scope call eval?
bool CallsEval();
- // Return the language mode of this scope.
- LanguageMode language_mode();
+ // Return the strict mode of this scope.
+ StrictMode strict_mode();
- // Does this scope make a non-strict eval call?
- bool CallsNonStrictEval() {
- return CallsEval() && (language_mode() == CLASSIC_MODE);
- }
+ // Does this scope make a sloppy eval call?
+ bool CallsSloppyEval() { return CallsEval() && strict_mode() == SLOPPY; }
// Return the total number of locals allocated on the stack and in the
// context. This includes the parameters that are allocated in the context.
@@ -4519,9 +4517,9 @@
// Properties of scopes.
class ScopeTypeField: public BitField<ScopeType, 0, 3> {};
class CallsEvalField: public BitField<bool, 3, 1> {};
- class LanguageModeField: public BitField<LanguageMode, 4, 2> {};
- class FunctionVariableField: public BitField<FunctionVariableInfo, 6, 2> {};
- class FunctionVariableMode: public BitField<VariableMode, 8, 3> {};
+ class StrictModeField: public BitField<StrictMode, 4, 1> {};
+ class FunctionVariableField: public BitField<FunctionVariableInfo, 5, 2> {};
+ class FunctionVariableMode: public BitField<VariableMode, 7, 3> {};
// BitFields representing the encoded information for context locals in the
// ContextLocalInfoEntries part.
@@ -5932,8 +5930,8 @@
return IsFastElementsKind(elements_kind());
}
- inline bool has_non_strict_arguments_elements() {
- return elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
+ inline bool has_sloppy_arguments_elements() {
+ return elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS;
}
inline bool has_external_array_elements() {
@@ -5950,7 +5948,7 @@
inline bool has_slow_elements_kind() {
return elements_kind() == DICTIONARY_ELEMENTS
- || elements_kind() == NON_STRICT_ARGUMENTS_ELEMENTS;
+ || elements_kind() == SLOPPY_ARGUMENTS_ELEMENTS;
}
static bool IsValidElementsTransition(ElementsKind from_kind,
@@ -6938,20 +6936,9 @@
// spending time attempting to optimize it again.
DECL_BOOLEAN_ACCESSORS(optimization_disabled)
- // Indicates the language mode of the function's code as defined by the
- // current harmony drafts for the next ES language standard. Possible
- // values are:
- // 1. CLASSIC_MODE - Unrestricted syntax and semantics, same as in ES5.
- // 2. STRICT_MODE - Restricted syntax and semantics, same as in ES5.
- // 3. EXTENDED_MODE - Only available under the harmony flag, not part of ES5.
- inline LanguageMode language_mode();
- inline void set_language_mode(LanguageMode language_mode);
-
- // Indicates whether the language mode of this function is CLASSIC_MODE.
- inline bool is_classic_mode();
-
- // Indicates whether the language mode of this function is EXTENDED_MODE.
- inline bool is_extended_mode();
+ // Indicates the language mode.
+ inline StrictMode strict_mode();
+ inline void set_strict_mode(StrictMode strict_mode);
// False if the function definitely does not allocate an arguments object.
DECL_BOOLEAN_ACCESSORS(uses_arguments)
@@ -7202,7 +7189,6 @@
kLiveObjectsMayExist,
kOptimizationDisabled,
kStrictModeFunction,
- kExtendedModeFunction,
kUsesArguments,
kHasDuplicateParameters,
kNative,
@@ -7247,26 +7233,18 @@
static const int kStrictModeBitWithinByte =
(kStrictModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
- static const int kExtendedModeBitWithinByte =
- (kExtendedModeFunction + kCompilerHintsSmiTagSize) % kBitsPerByte;
-
static const int kNativeBitWithinByte =
(kNative + kCompilerHintsSmiTagSize) % kBitsPerByte;
#if __BYTE_ORDER == __LITTLE_ENDIAN
static const int kStrictModeByteOffset = kCompilerHintsOffset +
(kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
- static const int kExtendedModeByteOffset = kCompilerHintsOffset +
- (kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte;
static const int kNativeByteOffset = kCompilerHintsOffset +
(kNative + kCompilerHintsSmiTagSize) / kBitsPerByte;
#elif __BYTE_ORDER == __BIG_ENDIAN
static const int kStrictModeByteOffset = kCompilerHintsOffset +
(kCompilerHintsSize - 1) -
((kStrictModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
- static const int kExtendedModeByteOffset = kCompilerHintsOffset +
- (kCompilerHintsSize - 1) -
- ((kExtendedModeFunction + kCompilerHintsSmiTagSize) / kBitsPerByte);
static const int kNativeByteOffset = kCompilerHintsOffset +
(kCompilerHintsSize - 1) -
((kNative + kCompilerHintsSmiTagSize) / kBitsPerByte);
@@ -8017,7 +7995,7 @@
Object* Lookup(String* src, Context* context);
Object* LookupEval(String* src,
Context* context,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position);
Object* LookupRegExp(String* source, JSRegExp::Flags flags);
MUST_USE_RESULT MaybeObject* Put(String* src,
@@ -8454,8 +8432,8 @@
};
-// Representation of a slow alias as part of a non-strict arguments objects.
-// For fast aliases (if HasNonStrictArgumentsElements()):
+// Representation of a slow alias as part of a sloppy arguments objects.
+// For fast aliases (if HasSloppyArgumentsElements()):
// - the parameter map contains an index into the context
// - all attributes of the element have default values
// For slow aliases (if HasDictionaryArgumentsElements()):
@@ -9633,7 +9611,7 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
bool* done);
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
@@ -9684,12 +9662,12 @@
Handle<Name> name,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> SetElementWithHandler(Handle<JSProxy> proxy,
Handle<JSReceiver> receiver,
uint32_t index,
Handle<Object> value,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static bool HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name);
static bool HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index);
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index d215070..fb3eac5 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -258,9 +258,13 @@
uint32_t offset = code->TranslateAstIdToPcOffset(info->osr_ast_id());
BackEdgeTable::RemoveStackCheck(code, offset);
} else {
- Handle<Code> code = Compiler::GetConcurrentlyOptimizedCode(job);
- function->ReplaceCode(
- code.is_null() ? function->shared()->code() : *code);
+ if (function->IsOptimized()) {
+ DisposeOptimizedCompileJob(job, false);
+ } else {
+ Handle<Code> code = Compiler::GetConcurrentlyOptimizedCode(job);
+ function->ReplaceCode(
+ code.is_null() ? function->shared()->code() : *code);
+ }
}
}
}
diff --git a/src/parser.cc b/src/parser.cc
index 9e456f0..c6c72fe 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -33,7 +33,6 @@
#include "char-predicates-inl.h"
#include "codegen.h"
#include "compiler.h"
-#include "func-name-inferrer.h"
#include "messages.h"
#include "parser.h"
#include "platform.h"
@@ -520,7 +519,7 @@
}
-Expression* ParserTraits::ExpressionFromLiteral(
+Literal* ParserTraits::ExpressionFromLiteral(
Token::Value token, int pos,
Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory) {
@@ -577,11 +576,6 @@
}
-Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
- return parser_->ParseObjectLiteral(ok);
-}
-
-
Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
return parser_->ParseAssignmentExpression(accept_IN, ok);
}
@@ -592,6 +586,20 @@
}
+FunctionLiteral* ParserTraits::ParseFunctionLiteral(
+ Handle<String> name,
+ Scanner::Location function_name_location,
+ bool name_is_strict_reserved,
+ bool is_generator,
+ int function_token_position,
+ FunctionLiteral::FunctionType type,
+ bool* ok) {
+ return parser_->ParseFunctionLiteral(name, function_name_location,
+ name_is_strict_reserved, is_generator,
+ function_token_position, type, ok);
+}
+
+
Parser::Parser(CompilationInfo* info)
: ParserBase<ParserTraits>(&scanner_,
info->isolate()->stack_guard()->real_climit(),
@@ -606,7 +614,6 @@
original_scope_(NULL),
target_stack_(NULL),
pre_parse_data_(NULL),
- fni_(NULL),
info_(info) {
ASSERT(!script_.is_null());
isolate_->set_ast_node_id(0);
@@ -682,7 +689,7 @@
}
original_scope_ = scope;
if (info->is_eval()) {
- if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
+ if (!scope->is_global_scope() || info->strict_mode() == STRICT) {
scope = NewScope(scope, EVAL_SCOPE);
}
} else if (info->is_global()) {
@@ -703,16 +710,16 @@
// Enters 'scope'.
FunctionState function_state(&function_state_, &scope_, scope, zone());
- scope_->SetLanguageMode(info->language_mode());
+ scope_->SetStrictMode(info->strict_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
int beg_pos = scanner()->location().beg_pos;
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
- if (ok && !scope_->is_classic_mode()) {
+ if (ok && strict_mode() == STRICT) {
CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
}
- if (ok && is_extended_mode()) {
+ if (ok && FLAG_harmony_scoping && strict_mode() == STRICT) {
CheckConflictingVarDeclarations(scope_, &ok);
}
@@ -817,11 +824,9 @@
}
original_scope_ = scope;
FunctionState function_state(&function_state_, &scope_, scope, zone());
- ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
- ASSERT(scope->language_mode() != EXTENDED_MODE ||
- info()->is_extended_mode());
- ASSERT(info()->language_mode() == shared_info->language_mode());
- scope->SetLanguageMode(shared_info->language_mode());
+ ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
+ ASSERT(info()->strict_mode() == shared_info->strict_mode());
+ scope->SetStrictMode(shared_info->strict_mode());
FunctionLiteral::FunctionType function_type = shared_info->is_expression()
? (shared_info->is_anonymous()
? FunctionLiteral::ANONYMOUS_EXPRESSION
@@ -897,7 +902,7 @@
Handle<String> directive = Handle<String>::cast(literal->value());
// Check "use strict" directive (ES5 14.1).
- if (scope_->is_classic_mode() &&
+ if (strict_mode() == SLOPPY &&
directive->Equals(isolate()->heap()->use_strict_string()) &&
token_loc.end_pos - token_loc.beg_pos ==
isolate()->heap()->use_strict_string()->length() + 2) {
@@ -914,9 +919,7 @@
scope_ = scope;
mode_ = PARSE_EAGERLY;
}
- // TODO(ES6): Fix entering extended mode, once it is specified.
- scope_->SetLanguageMode(allow_harmony_scoping()
- ? EXTENDED_MODE : STRICT_MODE);
+ scope_->SetStrictMode(STRICT);
// "use strict" is the only directive for now.
directive_prologue = false;
}
@@ -1058,7 +1061,7 @@
Expect(Token::LBRACE, CHECK_OK);
scope->set_start_position(scanner()->location().beg_pos);
- scope->SetLanguageMode(EXTENDED_MODE);
+ scope->SetStrictMode(STRICT);
{
BlockState block_state(&scope_, scope);
@@ -1443,7 +1446,7 @@
// In Harmony mode, this case also handles the extension:
// Statement:
// GeneratorDeclaration
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
ReportMessageAt(scanner()->peek_location(), "strict_function");
*ok = false;
return NULL;
@@ -1488,7 +1491,7 @@
// Similarly, strict mode eval scope does not leak variable declarations to
// the caller's scope so we declare all locals, too.
if (declaration_scope->is_function_scope() ||
- declaration_scope->is_strict_or_extended_eval_scope() ||
+ declaration_scope->is_strict_eval_scope() ||
declaration_scope->is_block_scope() ||
declaration_scope->is_module_scope() ||
declaration_scope->is_global_scope()) {
@@ -1521,8 +1524,8 @@
// because the var declaration is hoisted to the function scope where 'x'
// is already bound.
ASSERT(IsDeclaredVariableMode(var->mode()));
- if (is_extended_mode()) {
- // In harmony mode we treat re-declarations as early errors. See
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
+ // In harmony we treat re-declarations as early errors. See
// ES5 16 for a definition of early errors.
SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
const char* elms[2] = { "Variable", c_string.get() };
@@ -1559,7 +1562,7 @@
// Runtime::DeclareContextSlot() calls.
declaration_scope->AddDeclaration(declaration);
- if (mode == CONST && declaration_scope->is_global_scope()) {
+ if (mode == CONST_LEGACY && declaration_scope->is_global_scope()) {
// For global const variables we bind the proxy to a variable.
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
@@ -1567,8 +1570,8 @@
declaration_scope, name, mode, true, kind,
kNeedsInitialization, proxy->interface());
} else if (declaration_scope->is_eval_scope() &&
- declaration_scope->is_classic_mode()) {
- // For variable declarations in a non-strict eval scope the proxy is bound
+ declaration_scope->strict_mode() == SLOPPY) {
+ // For variable declarations in a sloppy eval scope the proxy is bound
// to a lookup variable to force a dynamic declaration using the
// DeclareContextSlot runtime function.
Variable::Kind kind = Variable::NORMAL;
@@ -1699,7 +1702,8 @@
// In extended mode, a function behaves as a lexical binding, except in the
// global scope.
VariableMode mode =
- is_extended_mode() && !scope_->is_global_scope() ? LET : VAR;
+ FLAG_harmony_scoping &&
+ strict_mode() == STRICT && !scope_->is_global_scope() ? LET : VAR;
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
@@ -1710,7 +1714,9 @@
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
- if (scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
+ return ParseScopedBlock(labels, ok);
+ }
// Block ::
// '{' Statement* '}'
@@ -1826,29 +1832,31 @@
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
//
- // However disallowing const in classic mode will break compatibility with
+ // However disallowing const in sloppy mode will break compatibility with
// existing pages. Therefore we keep allowing const with the old
- // non-harmony semantics in classic mode.
+ // non-harmony semantics in sloppy mode.
Consume(Token::CONST);
- switch (scope_->language_mode()) {
- case CLASSIC_MODE:
- mode = CONST;
- init_op = Token::INIT_CONST;
+ switch (strict_mode()) {
+ case SLOPPY:
+ mode = CONST_LEGACY;
+ init_op = Token::INIT_CONST_LEGACY;
break;
- case STRICT_MODE:
- ReportMessage("strict_const", Vector<const char*>::empty());
- *ok = false;
- return NULL;
- case EXTENDED_MODE:
- if (var_context == kStatement) {
- // In extended mode 'const' declarations are only allowed in source
- // element positions.
- ReportMessage("unprotected_const", Vector<const char*>::empty());
+ case STRICT:
+ if (FLAG_harmony_scoping) {
+ if (var_context == kStatement) {
+ // In strict mode 'const' declarations are only allowed in source
+ // element positions.
+ ReportMessage("unprotected_const", Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ }
+ mode = CONST;
+ init_op = Token::INIT_CONST;
+ } else {
+ ReportMessage("strict_const", Vector<const char*>::empty());
*ok = false;
return NULL;
}
- mode = CONST_HARMONY;
- init_op = Token::INIT_CONST_HARMONY;
}
is_const = true;
needs_init = true;
@@ -1859,7 +1867,9 @@
//
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
- if (!is_extended_mode()) {
+ //
+ // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
+ if (!FLAG_harmony_scoping || strict_mode() == SLOPPY) {
ReportMessage("illegal_let", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -1964,7 +1974,7 @@
Expression* value = NULL;
int pos = -1;
// Harmony consts have non-optional initializers.
- if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
+ if (peek() == Token::ASSIGN || mode == CONST) {
Expect(Token::ASSIGN, CHECK_OK);
pos = position();
value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
@@ -2032,8 +2042,8 @@
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
- LanguageMode language_mode = initialization_scope->language_mode();
- arguments->Add(factory()->NewNumberLiteral(language_mode, pos), zone());
+ StrictMode strict_mode = initialization_scope->strict_mode();
+ arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
@@ -2333,7 +2343,7 @@
Expect(Token::WITH, CHECK_OK);
int pos = position();
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
ReportMessage("strict_mode_with", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2485,7 +2495,8 @@
Expect(Token::RPAREN, CHECK_OK);
Target target(&this->target_stack_, &catch_collector);
- VariableMode mode = is_extended_mode() ? LET : VAR;
+ VariableMode mode =
+ FLAG_harmony_scoping && strict_mode() == STRICT ? LET : VAR;
catch_variable =
catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
@@ -2907,7 +2918,7 @@
expression = NewThrowReferenceError(message);
}
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
// Assignment to eval or arguments is disallowed in strict mode.
CheckStrictModeLValue(expression, CHECK_OK);
}
@@ -2941,7 +2952,7 @@
// name if we're dealing with "a = function(){...}();"-like
// expression.
if ((op == Token::INIT_VAR
- || op == Token::INIT_CONST
+ || op == Token::INIT_CONST_LEGACY
|| op == Token::ASSIGN)
&& (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
fni_->Infer();
@@ -3131,7 +3142,7 @@
}
// "delete identifier" is a syntax error in strict mode.
- if (op == Token::DELETE && !scope_->is_classic_mode()) {
+ if (op == Token::DELETE && strict_mode() == STRICT) {
VariableProxy* operand = expression->AsVariableProxy();
if (operand != NULL && !operand->is_this()) {
ReportMessage("strict_delete", Vector<const char*>::empty());
@@ -3179,7 +3190,7 @@
expression = NewThrowReferenceError(message);
}
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
// Prefix expression operand in strict mode may not be eval or arguments.
CheckStrictModeLValue(expression, CHECK_OK);
}
@@ -3213,7 +3224,7 @@
expression = NewThrowReferenceError(message);
}
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
// Postfix expression operand in strict mode may not be eval or arguments.
CheckStrictModeLValue(expression, CHECK_OK);
}
@@ -3490,192 +3501,6 @@
}
-Expression* Parser::ParseObjectLiteral(bool* ok) {
- // ObjectLiteral ::
- // '{' ((
- // ((IdentifierName | String | Number) ':' AssignmentExpression) |
- // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
- // ) ',')* '}'
- // (Except that trailing comma is not required and not allowed.)
-
- int pos = peek_position();
- ZoneList<ObjectLiteral::Property*>* properties =
- new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
- int number_of_boilerplate_properties = 0;
- bool has_function = false;
-
- ObjectLiteralChecker checker(this, scope_->language_mode());
-
- Expect(Token::LBRACE, CHECK_OK);
-
- while (peek() != Token::RBRACE) {
- if (fni_ != NULL) fni_->Enter();
-
- Literal* key = NULL;
- Token::Value next = peek();
- int next_pos = peek_position();
-
- switch (next) {
- case Token::FUTURE_RESERVED_WORD:
- case Token::FUTURE_STRICT_RESERVED_WORD:
- case Token::IDENTIFIER: {
- bool is_getter = false;
- bool is_setter = false;
- Handle<String> id =
- ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
- if (fni_ != NULL) fni_->PushLiteralName(id);
-
- 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.
- Token::Value next = Next();
- if (next != i::Token::IDENTIFIER &&
- next != i::Token::FUTURE_RESERVED_WORD &&
- next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
- next != i::Token::NUMBER &&
- next != i::Token::STRING &&
- !Token::IsKeyword(next)) {
- ReportUnexpectedToken(next);
- *ok = false;
- return NULL;
- }
- // Validate the property.
- PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
- checker.CheckProperty(next, type, CHECK_OK);
- Handle<String> name = GetSymbol();
- FunctionLiteral* value =
- ParseFunctionLiteral(name,
- scanner()->location(),
- false, // reserved words are allowed here
- false, // not a generator
- RelocInfo::kNoPosition,
- FunctionLiteral::ANONYMOUS_EXPRESSION,
- CHECK_OK);
- // Allow any number of parameters for compatibilty with JSC.
- // Specification only allows zero parameters for get and one for set.
- ObjectLiteral::Property* property =
- factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
- if (ObjectLiteral::IsBoilerplateProperty(property)) {
- number_of_boilerplate_properties++;
- }
- properties->Add(property, zone());
- if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
- if (fni_ != NULL) {
- fni_->Infer();
- fni_->Leave();
- }
- continue; // restart the while
- }
- // 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()->NewLiteral(id, next_pos);
- break;
- }
- case Token::STRING: {
- Consume(Token::STRING);
- Handle<String> string = GetSymbol();
- if (fni_ != NULL) fni_->PushLiteralName(string);
- uint32_t index;
- if (!string.is_null() && string->AsArrayIndex(&index)) {
- key = factory()->NewNumberLiteral(index, next_pos);
- break;
- }
- key = factory()->NewLiteral(string, next_pos);
- break;
- }
- case Token::NUMBER: {
- Consume(Token::NUMBER);
- ASSERT(scanner()->is_literal_ascii());
- double value = StringToDouble(isolate()->unicode_cache(),
- scanner()->literal_ascii_string(),
- ALLOW_HEX | ALLOW_OCTAL |
- ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
- key = factory()->NewNumberLiteral(value, next_pos);
- break;
- }
- default:
- if (Token::IsKeyword(next)) {
- Consume(next);
- Handle<String> string = GetSymbol();
- key = factory()->NewLiteral(string, next_pos);
- } else {
- Token::Value next = Next();
- ReportUnexpectedToken(next);
- *ok = false;
- return NULL;
- }
- }
-
- // Validate the property
- checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
- Expect(Token::COLON, CHECK_OK);
- Expression* value = ParseAssignmentExpression(true, CHECK_OK);
-
- ObjectLiteral::Property* property =
- factory()->NewObjectLiteralProperty(key, value);
-
- // Mark top-level object literals that contain function literals and
- // pretenure the literal so it can be added as a constant function
- // property.
- if (scope_->DeclarationScope()->is_global_scope() &&
- value->AsFunctionLiteral() != NULL) {
- has_function = true;
- value->AsFunctionLiteral()->set_pretenure();
- }
-
- // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
- if (ObjectLiteral::IsBoilerplateProperty(property)) {
- number_of_boilerplate_properties++;
- }
- properties->Add(property, zone());
-
- // TODO(1240767): Consider allowing trailing comma.
- if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
- if (fni_ != NULL) {
- fni_->Infer();
- fni_->Leave();
- }
- }
- Expect(Token::RBRACE, CHECK_OK);
-
- // Computation of literal_index must happen before pre parse bailout.
- int literal_index = function_state_->NextMaterializedLiteralIndex();
-
- return factory()->NewObjectLiteral(properties,
- literal_index,
- number_of_boilerplate_properties,
- has_function,
- pos);
-}
-
-
-ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
- // Arguments ::
- // '(' (AssignmentExpression)*[','] ')'
-
- ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4, zone());
- Expect(Token::LPAREN, CHECK_OK);
- bool done = (peek() == Token::RPAREN);
- while (!done) {
- Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
- result->Add(argument, zone());
- if (result->length() > Code::kMaxArguments) {
- ReportMessageAt(scanner()->location(), "too_many_arguments");
- *ok = false;
- return NULL;
- }
- done = (peek() == Token::RPAREN);
- if (!done) Expect(Token::COMMA, CHECK_OK);
- }
- Expect(Token::RPAREN, CHECK_OK);
- return result;
-}
-
-
class SingletonLogger : public ParserRecorder {
public:
SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
@@ -3687,13 +3512,13 @@
int end,
int literals,
int properties,
- LanguageMode mode) {
+ StrictMode strict_mode) {
ASSERT(!has_error_);
start_ = start;
end_ = end;
literals_ = literals;
properties_ = properties;
- mode_ = mode;
+ strict_mode_ = strict_mode;
};
// Logs a symbol creation of a literal or identifier.
@@ -3742,9 +3567,9 @@
ASSERT(!has_error_);
return properties_;
}
- LanguageMode language_mode() {
+ StrictMode strict_mode() {
ASSERT(!has_error_);
- return mode_;
+ return strict_mode_;
}
const char* message() {
ASSERT(has_error_);
@@ -3762,7 +3587,7 @@
// For function entries.
int literals_;
int properties_;
- LanguageMode mode_;
+ StrictMode strict_mode_;
// For error messages.
const char* message_;
const char* argument_opt_;
@@ -3824,7 +3649,8 @@
Scope* declaration_scope = scope_->DeclarationScope();
Scope* original_declaration_scope = original_scope_->DeclarationScope();
Scope* scope =
- function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
+ function_type == FunctionLiteral::DECLARATION &&
+ (!FLAG_harmony_scoping || strict_mode() == SLOPPY) &&
(original_scope_ == original_declaration_scope ||
declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE)
@@ -3913,10 +3739,13 @@
// future we can change the AST to only refer to VariableProxies
// instead of Variables and Proxis as is the case now.
Variable* fvar = NULL;
- Token::Value fvar_init_op = Token::INIT_CONST;
+ Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
- if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
- VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
+ fvar_init_op = Token::INIT_CONST;
+ }
+ VariableMode fvar_mode = FLAG_harmony_scoping && strict_mode() == STRICT
+ ? CONST : CONST_LEGACY;
fvar = new(zone()) Variable(scope_,
function_name, fvar_mode, true /* is valid LHS */,
Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
@@ -3986,7 +3815,7 @@
scope->end_position() - function_block_pos);
materialized_literal_count = entry.literal_count();
expected_property_count = entry.property_count();
- scope_->SetLanguageMode(entry.language_mode());
+ scope_->SetStrictMode(entry.strict_mode());
} else {
// This case happens when we have preparse data but it doesn't contain
// an entry for the function. As a safety net, fall back to eager
@@ -4034,7 +3863,7 @@
scope->end_position() - function_block_pos);
materialized_literal_count = logger.literals();
expected_property_count = logger.properties();
- scope_->SetLanguageMode(logger.language_mode());
+ scope_->SetStrictMode(logger.strict_mode());
}
}
@@ -4098,7 +3927,7 @@
// Validate strict mode. We can do this only after parsing the function,
// since the function can declare itself strict.
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
if (IsEvalOrArguments(function_name)) {
ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;
@@ -4133,7 +3962,7 @@
dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
}
- if (is_extended_mode()) {
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
CheckConflictingVarDeclarations(scope, CHECK_OK);
}
@@ -4179,7 +4008,7 @@
allow_harmony_numeric_literals());
}
PreParser::PreParseResult result =
- reusable_preparser_->PreParseLazyFunction(scope_->language_mode(),
+ reusable_preparser_->PreParseLazyFunction(strict_mode(),
is_generator(),
logger);
return result;
@@ -4261,7 +4090,7 @@
// in strict mode.
void Parser::CheckStrictModeLValue(Expression* expression,
bool* ok) {
- ASSERT(!scope_->is_classic_mode());
+ ASSERT(strict_mode() == STRICT);
VariableProxy* lhs = expression != NULL
? expression->AsVariableProxy()
: NULL;
diff --git a/src/parser.h b/src/parser.h
index 4a2cb02..799ec58 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -39,7 +39,6 @@
namespace internal {
class CompilationInfo;
-class FuncNameInferrer;
class ParserLog;
class PositionStack;
class Target;
@@ -54,7 +53,7 @@
kEndPositionIndex,
kLiteralCountIndex,
kPropertyCountIndex,
- kLanguageModeIndex,
+ kStrictModeIndex,
kSize
};
@@ -67,11 +66,10 @@
int end_pos() { return backing_[kEndPositionIndex]; }
int literal_count() { return backing_[kLiteralCountIndex]; }
int property_count() { return backing_[kPropertyCountIndex]; }
- LanguageMode language_mode() {
- ASSERT(backing_[kLanguageModeIndex] == CLASSIC_MODE ||
- backing_[kLanguageModeIndex] == STRICT_MODE ||
- backing_[kLanguageModeIndex] == EXTENDED_MODE);
- return static_cast<LanguageMode>(backing_[kLanguageModeIndex]);
+ StrictMode strict_mode() {
+ ASSERT(backing_[kStrictModeIndex] == SLOPPY ||
+ backing_[kStrictModeIndex] == STRICT);
+ return static_cast<StrictMode>(backing_[kStrictModeIndex]);
}
bool is_valid() { return !backing_.is_empty(); }
@@ -421,7 +419,11 @@
// Return types for traversing functions.
typedef Handle<String> Identifier;
typedef v8::internal::Expression* Expression;
+ typedef v8::internal::FunctionLiteral* FunctionLiteral;
+ typedef v8::internal::Literal* Literal;
+ typedef ObjectLiteral::Property* ObjectLiteralProperty;
typedef ZoneList<v8::internal::Expression*>* ExpressionList;
+ typedef ZoneList<ObjectLiteral::Property*>* PropertyList;
};
explicit ParserTraits(Parser* parser) : parser_(parser) {}
@@ -446,6 +448,27 @@
// Helper functions for recursive descent.
bool IsEvalOrArguments(Handle<String> identifier) const;
+ static bool IsBoilerplateProperty(ObjectLiteral::Property* property) {
+ return ObjectLiteral::IsBoilerplateProperty(property);
+ }
+
+ static bool IsArrayIndex(Handle<String> string, uint32_t* index) {
+ return !string.is_null() && string->AsArrayIndex(index);
+ }
+
+ static void PushLiteralName(FuncNameInferrer* fni, Handle<String> id) {
+ fni->PushLiteralName(id);
+ }
+
+ static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+ Scope* scope, Expression* value, bool* has_function) {
+ if (scope->DeclarationScope()->is_global_scope() &&
+ value->AsFunctionLiteral() != NULL) {
+ *has_function = true;
+ value->AsFunctionLiteral()->set_pretenure();
+ }
+ }
+
// Reporting errors.
void ReportMessageAt(Scanner::Location source_location,
const char* message,
@@ -462,6 +485,12 @@
static Expression* EmptyExpression() {
return NULL;
}
+ static Literal* EmptyLiteral() {
+ return NULL;
+ }
+ static ZoneList<Expression*>* NullExpressionList() {
+ return NULL;
+ }
// Odd-ball literal creators.
Literal* GetLiteralTheHole(int position,
@@ -473,7 +502,7 @@
PretenureFlag tenured);
Expression* ThisExpression(Scope* scope,
AstNodeFactory<AstConstructionVisitor>* factory);
- Expression* ExpressionFromLiteral(
+ Literal* ExpressionFromLiteral(
Token::Value token, int pos, Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory);
Expression* ExpressionFromIdentifier(
@@ -485,11 +514,21 @@
ZoneList<v8::internal::Expression*>* NewExpressionList(int size, Zone* zone) {
return new(zone) ZoneList<v8::internal::Expression*>(size, zone);
}
+ ZoneList<ObjectLiteral::Property*>* NewPropertyList(int size, Zone* zone) {
+ return new(zone) ZoneList<ObjectLiteral::Property*>(size, zone);
+ }
// Temporary glue; these functions will move to ParserBase.
- Expression* ParseObjectLiteral(bool* ok);
Expression* ParseAssignmentExpression(bool accept_IN, bool* ok);
Expression* ParseV8Intrinsic(bool* ok);
+ FunctionLiteral* ParseFunctionLiteral(
+ Handle<String> name,
+ Scanner::Location function_name_location,
+ bool name_is_strict_reserved,
+ bool is_generator,
+ int function_token_position,
+ FunctionLiteral::FunctionType type,
+ bool* ok);
private:
Parser* parser_;
@@ -578,10 +617,6 @@
bool inside_with() const { return scope_->inside_with(); }
Mode mode() const { return mode_; }
ScriptDataImpl* pre_parse_data() const { return pre_parse_data_; }
- bool is_extended_mode() {
- ASSERT(scope_ != NULL);
- return scope_->is_extended_mode();
- }
Scope* DeclarationScope(VariableMode mode) {
return IsLexicalVariableMode(mode)
? scope_ : scope_->DeclarationScope();
@@ -655,7 +690,6 @@
Expression* subject,
Statement* body);
- ZoneList<Expression*>* ParseArguments(bool* ok);
FunctionLiteral* ParseFunctionLiteral(
Handle<String> name,
Scanner::Location function_name_location,
@@ -754,7 +788,6 @@
Scope* original_scope_; // for ES5 function declarations in sloppy eval
Target* target_stack_; // for break, continue statements
ScriptDataImpl* pre_parse_data_;
- FuncNameInferrer* fni_;
Mode mode_;
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index c91cf24..94aabe8 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -363,6 +363,9 @@
}
+void OS::TimeZoneChanged() {}
+
+
int OS::GetLastError() {
return errno;
}
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 52c3050..afcd82b 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -251,6 +251,8 @@
// timestamp taking into account daylight saving.
char* LocalTimezone();
+ static void TimeZoneChanged() { tz_initialized_ = false; }
+
private:
// Constants for time conversion.
static const int64_t kTimeEpoc = 116444736000000000LL;
@@ -611,6 +613,11 @@
}
+void OS::TimeZoneChanged() {
+ Win32Time::TimeZoneChanged();
+}
+
+
int OS::GetLastError() {
return ::GetLastError();
}
diff --git a/src/platform.h b/src/platform.h
index 8af90f1..d424666 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -193,6 +193,8 @@
// Returns the daylight savings offset for the given time.
static double DaylightSavingsOffset(double time);
+ static void TimeZoneChanged();
+
// Returns last OS error.
static int GetLastError();
diff --git a/src/preparse-data.h b/src/preparse-data.h
index 15b0310..2bc42bd 100644
--- a/src/preparse-data.h
+++ b/src/preparse-data.h
@@ -49,7 +49,7 @@
int end,
int literals,
int properties,
- LanguageMode language_mode) = 0;
+ StrictMode strict_mode) = 0;
// Logs a symbol creation of a literal or identifier.
virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
@@ -89,12 +89,12 @@
int end,
int literals,
int properties,
- LanguageMode language_mode) {
+ StrictMode strict_mode) {
function_store_.Add(start);
function_store_.Add(end);
function_store_.Add(literals);
function_store_.Add(properties);
- function_store_.Add(language_mode);
+ function_store_.Add(strict_mode);
}
// Logs an error message and marks the log as containing an error.
diff --git a/src/preparser.cc b/src/preparser.cc
index dfda980..a111fe7 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -122,11 +122,6 @@
}
-PreParserExpression PreParserTraits::ParseObjectLiteral(bool* ok) {
- return pre_parser_->ParseObjectLiteral(ok);
-}
-
-
PreParserExpression PreParserTraits::ParseAssignmentExpression(bool accept_IN,
bool* ok) {
return pre_parser_->ParseAssignmentExpression(accept_IN, ok);
@@ -138,13 +133,27 @@
}
+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,
+ bool* ok) {
+ return pre_parser_->ParseFunctionLiteral(
+ name, function_name_location, name_is_strict_reserved, is_generator,
+ function_token_position, type, ok);
+}
+
+
PreParser::PreParseResult PreParser::PreParseLazyFunction(
- LanguageMode mode, bool is_generator, ParserRecorder* log) {
+ StrictMode strict_mode, bool is_generator, ParserRecorder* log) {
log_ = log;
// Lazy functions always have trivial outer scopes (no with/catch scopes).
PreParserScope top_scope(scope_, GLOBAL_SCOPE);
FunctionState top_state(&function_state_, &scope_, &top_scope);
- scope_->SetLanguageMode(mode);
+ scope_->SetStrictMode(strict_mode);
PreParserScope function_scope(scope_, FUNCTION_SCOPE);
FunctionState function_state(&function_state_, &scope_, &function_scope);
function_state.set_is_generator(is_generator);
@@ -157,7 +166,7 @@
ReportUnexpectedToken(scanner()->current_token());
} else {
ASSERT_EQ(Token::RBRACE, scanner()->peek());
- if (!scope_->is_classic_mode()) {
+ if (scope_->strict_mode() == STRICT) {
int end_pos = scanner()->location().end_pos;
CheckOctalLiteral(start_position, end_pos, &ok);
}
@@ -224,8 +233,7 @@
Statement statement = ParseSourceElement(CHECK_OK);
if (directive_prologue) {
if (statement.IsUseStrictLiteral()) {
- scope_->SetLanguageMode(allow_harmony_scoping() ?
- EXTENDED_MODE : STRICT_MODE);
+ scope_->SetStrictMode(STRICT);
} else if (!statement.IsStringLiteral()) {
directive_prologue = false;
}
@@ -319,7 +327,7 @@
Scanner::Location start_location = scanner()->peek_location();
Statement statement = ParseFunctionDeclaration(CHECK_OK);
Scanner::Location end_location = scanner()->location();
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
PreParserTraits::ReportMessageAt(start_location.beg_pos,
end_location.end_pos,
"strict_function",
@@ -372,7 +380,7 @@
//
Expect(Token::LBRACE, CHECK_OK);
while (peek() != Token::RBRACE) {
- if (scope_->is_extended_mode()) {
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
ParseSourceElement(CHECK_OK);
} else {
ParseStatement(CHECK_OK);
@@ -432,28 +440,24 @@
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
//
- // However disallowing const in classic mode will break compatibility with
+ // However disallowing const in sloppy mode will break compatibility with
// existing pages. Therefore we keep allowing const with the old
- // non-harmony semantics in classic mode.
+ // non-harmony semantics in sloppy mode.
Consume(Token::CONST);
- switch (scope_->language_mode()) {
- case CLASSIC_MODE:
- break;
- case STRICT_MODE: {
- Scanner::Location location = scanner()->peek_location();
- ReportMessageAt(location, "strict_const");
- *ok = false;
- return Statement::Default();
- }
- case EXTENDED_MODE:
- if (var_context != kSourceElement &&
- var_context != kForStatement) {
+ if (strict_mode() == STRICT) {
+ if (FLAG_harmony_scoping) {
+ if (var_context != kSourceElement && var_context != kForStatement) {
ReportMessageAt(scanner()->peek_location(), "unprotected_const");
*ok = false;
return Statement::Default();
}
require_initializer = true;
- break;
+ } else {
+ Scanner::Location location = scanner()->peek_location();
+ ReportMessageAt(location, "strict_const");
+ *ok = false;
+ return Statement::Default();
+ }
}
} else if (peek() == Token::LET) {
// ES6 Draft Rev4 section 12.2.1:
@@ -462,7 +466,9 @@
//
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
- if (!scope_->is_extended_mode()) {
+ //
+ // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
+ if (!FLAG_harmony_scoping || strict_mode() == SLOPPY) {
ReportMessageAt(scanner()->peek_location(), "illegal_let");
*ok = false;
return Statement::Default();
@@ -515,7 +521,7 @@
// Expression is a single identifier, and not, e.g., a parenthesized
// identifier.
ASSERT(!expr.AsIdentifier().IsFutureReserved());
- ASSERT(scope_->is_classic_mode() ||
+ ASSERT(strict_mode() == SLOPPY ||
(!expr.AsIdentifier().IsFutureStrictReserved() &&
!expr.AsIdentifier().IsYield()));
Consume(Token::COLON);
@@ -613,7 +619,7 @@
// WithStatement ::
// 'with' '(' Expression ')' Statement
Expect(Token::WITH, CHECK_OK);
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
ReportMessageAt(scanner()->location(), "strict_mode_with");
*ok = false;
return Statement::Default();
@@ -852,7 +858,7 @@
return expression;
}
- if (!scope_->is_classic_mode() &&
+ if (strict_mode() == STRICT &&
expression.IsIdentifier() &&
expression.AsIdentifier().IsEvalOrArguments()) {
Scanner::Location after = scanner()->location();
@@ -946,7 +952,7 @@
op = Next();
Scanner::Location before = scanner()->peek_location();
Expression expression = ParseUnaryExpression(CHECK_OK);
- if (!scope_->is_classic_mode() &&
+ if (strict_mode() == STRICT &&
expression.IsIdentifier() &&
expression.AsIdentifier().IsEvalOrArguments()) {
Scanner::Location after = scanner()->location();
@@ -969,7 +975,7 @@
Expression expression = ParseLeftHandSideExpression(CHECK_OK);
if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
Token::IsCountOp(peek())) {
- if (!scope_->is_classic_mode() &&
+ if (strict_mode() == STRICT &&
expression.IsIdentifier() &&
expression.AsIdentifier().IsEvalOrArguments()) {
Scanner::Location after = scanner()->location();
@@ -1129,113 +1135,6 @@
}
-PreParser::Expression PreParser::ParseObjectLiteral(bool* ok) {
- // ObjectLiteral ::
- // '{' ((
- // ((IdentifierName | String | Number) ':' AssignmentExpression) |
- // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
- // ) ',')* '}'
- // (Except that trailing comma is not required and not allowed.)
-
- ObjectLiteralChecker checker(this, scope_->language_mode());
-
- Expect(Token::LBRACE, CHECK_OK);
- while (peek() != Token::RBRACE) {
- Token::Value next = peek();
- switch (next) {
- case Token::IDENTIFIER:
- case Token::FUTURE_RESERVED_WORD:
- case Token::FUTURE_STRICT_RESERVED_WORD: {
- bool is_getter = false;
- bool is_setter = false;
- ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
- if ((is_getter || is_setter) && peek() != Token::COLON) {
- Token::Value next = Next();
- if (next != Token::IDENTIFIER &&
- next != Token::FUTURE_RESERVED_WORD &&
- next != Token::FUTURE_STRICT_RESERVED_WORD &&
- next != Token::NUMBER &&
- next != Token::STRING &&
- !Token::IsKeyword(next)) {
- ReportUnexpectedToken(next);
- *ok = false;
- return Expression::Default();
- }
- // Validate the property
- PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
- checker.CheckProperty(next, type, CHECK_OK);
- PreParserIdentifier name = GetSymbol(scanner());
- ParseFunctionLiteral(name,
- scanner()->location(),
- false, // reserved words are allowed here
- false, // not a generator
- RelocInfo::kNoPosition,
- FunctionLiteral::ANONYMOUS_EXPRESSION,
- CHECK_OK);
- if (peek() != Token::RBRACE) {
- Expect(Token::COMMA, CHECK_OK);
- }
- continue; // restart the while
- }
- break;
- }
- case Token::STRING:
- Consume(next);
- LogSymbol();
- break;
- case Token::NUMBER:
- Consume(next);
- break;
- default:
- if (Token::IsKeyword(next)) {
- Consume(next);
- LogSymbol();
- } else {
- Token::Value next = Next();
- ReportUnexpectedToken(next);
- *ok = false;
- return Expression::Default();
- }
- }
-
- // Validate the property
- checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
- Expect(Token::COLON, CHECK_OK);
- ParseAssignmentExpression(true, CHECK_OK);
-
- // TODO(1240767): Consider allowing trailing comma.
- if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
- }
- Expect(Token::RBRACE, CHECK_OK);
-
- function_state_->NextMaterializedLiteralIndex();
- return Expression::Default();
-}
-
-
-PreParser::Arguments PreParser::ParseArguments(bool* ok) {
- // Arguments ::
- // '(' (AssignmentExpression)*[','] ')'
-
- Expect(Token::LPAREN, ok);
- if (!*ok) return -1;
- bool done = (peek() == Token::RPAREN);
- int argc = 0;
- while (!done) {
- ParseAssignmentExpression(true, ok);
- if (!*ok) return -1;
- argc++;
- done = (peek() == Token::RPAREN);
- if (!done) {
- Expect(Token::COMMA, ok);
- if (!*ok) return -1;
- }
- }
- Expect(Token::RPAREN, ok);
- return argc;
-}
-
PreParser::Expression PreParser::ParseFunctionLiteral(
Identifier function_name,
Scanner::Location function_name_location,
@@ -1313,7 +1212,7 @@
// Validate strict mode. We can do this only after parsing the function,
// since the function can declare itself strict.
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
if (function_name.IsEvalOrArguments()) {
ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;
@@ -1362,7 +1261,7 @@
log_->LogFunction(body_start, body_end,
function_state_->materialized_literal_count(),
function_state_->expected_property_count(),
- scope_->language_mode());
+ strict_mode());
}
diff --git a/src/preparser.h b/src/preparser.h
index 8a5517e..59a9a61 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -28,6 +28,7 @@
#ifndef V8_PREPARSER_H
#define V8_PREPARSER_H
+#include "func-name-inferrer.h"
#include "hashmap.h"
#include "scopes.h"
#include "token.h"
@@ -50,6 +51,7 @@
scope_(NULL),
function_state_(NULL),
extension_(extension),
+ fni_(NULL),
scanner_(scanner),
stack_limit_(stack_limit),
stack_overflow_(false),
@@ -297,8 +299,7 @@
return function_state_->factory();
}
- bool is_classic_mode() const { return scope_->is_classic_mode(); }
-
+ StrictMode strict_mode() { return scope_->strict_mode(); }
bool is_generator() const { return function_state_->is_generator(); }
// Report syntax errors.
@@ -331,8 +332,8 @@
typename Traits::Type::Identifier ParseIdentifierName(bool* ok);
// Parses an identifier and determines whether or not it is 'get' or 'set'.
typename Traits::Type::Identifier ParseIdentifierNameOrGetOrSet(bool* is_get,
- bool* is_set,
- bool* ok);
+ bool* is_set,
+ bool* ok);
typename Traits::Type::Expression ParseRegExpLiteral(bool seen_equal,
bool* ok);
@@ -340,6 +341,8 @@
typename Traits::Type::Expression ParsePrimaryExpression(bool* ok);
typename Traits::Type::Expression ParseExpression(bool accept_IN, bool* ok);
typename Traits::Type::Expression ParseArrayLiteral(bool* ok);
+ typename Traits::Type::Expression ParseObjectLiteral(bool* ok);
+ typename Traits::Type::ExpressionList ParseArguments(bool* ok);
// Used to detect duplicates in object literals. Each of the values
// kGetterProperty, kSetterProperty and kValueProperty represents
@@ -365,10 +368,10 @@
// Validation per ECMA 262 - 11.1.5 "Object Initialiser".
class ObjectLiteralChecker {
public:
- ObjectLiteralChecker(ParserBase* parser, LanguageMode mode)
+ ObjectLiteralChecker(ParserBase* parser, StrictMode strict_mode)
: parser_(parser),
finder_(scanner()->unicode_cache()),
- language_mode_(mode) { }
+ strict_mode_(strict_mode) { }
void CheckProperty(Token::Value property, PropertyKind type, bool* ok);
@@ -392,7 +395,7 @@
ParserBase* parser_;
DuplicateFinder finder_;
- LanguageMode language_mode_;
+ StrictMode strict_mode_;
};
// If true, the next (and immediately following) function literal is
@@ -404,6 +407,7 @@
typename Traits::Type::Scope* scope_; // Scope stack.
FunctionState* function_state_; // Function state stack.
v8::Extension* extension_;
+ FuncNameInferrer* fni_;
private:
Scanner* scanner_;
@@ -553,8 +557,12 @@
class PreParserExpressionList {
public:
// These functions make list->Add(some_expression) work (and do nothing).
+ PreParserExpressionList() : length_(0) {}
PreParserExpressionList* operator->() { return this; }
- void Add(PreParserExpression, void*) { }
+ void Add(PreParserExpression, void*) { ++length_; }
+ int length() const { return length_; }
+ private:
+ int length_;
};
@@ -563,36 +571,27 @@
explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type)
: scope_type_(scope_type) {
if (outer_scope) {
- scope_inside_with_ =
- outer_scope->scope_inside_with_ || is_with_scope();
- language_mode_ = outer_scope->language_mode();
+ scope_inside_with_ = outer_scope->scope_inside_with_ || is_with_scope();
+ strict_mode_ = outer_scope->strict_mode();
} else {
scope_inside_with_ = is_with_scope();
- language_mode_ = CLASSIC_MODE;
+ strict_mode_ = SLOPPY;
}
}
bool is_with_scope() const { return scope_type_ == WITH_SCOPE; }
- bool is_classic_mode() const {
- return language_mode() == CLASSIC_MODE;
- }
- bool is_extended_mode() {
- return language_mode() == EXTENDED_MODE;
- }
bool inside_with() const {
return scope_inside_with_;
}
ScopeType type() { return scope_type_; }
- LanguageMode language_mode() const { return language_mode_; }
- void SetLanguageMode(LanguageMode language_mode) {
- language_mode_ = language_mode;
- }
+ StrictMode strict_mode() const { return strict_mode_; }
+ void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
private:
ScopeType scope_type_;
bool scope_inside_with_;
- LanguageMode language_mode_;
+ StrictMode strict_mode_;
};
@@ -616,6 +615,35 @@
int pos) {
return PreParserExpression::Default();
}
+
+ PreParserExpression NewObjectLiteralProperty(bool is_getter,
+ PreParserExpression value,
+ int pos) {
+ return PreParserExpression::Default();
+ }
+
+ PreParserExpression NewObjectLiteralProperty(PreParserExpression key,
+ PreParserExpression value) {
+ return PreParserExpression::Default();
+ }
+
+ PreParserExpression NewObjectLiteral(PreParserExpressionList properties,
+ int literal_index,
+ int boilerplate_properties,
+ bool has_function,
+ int pos) {
+ return PreParserExpression::Default();
+ }
+
+ PreParserExpression NewLiteral(PreParserIdentifier identifier,
+ int pos) {
+ return PreParserExpression::Default();
+ }
+
+ PreParserExpression NewNumberLiteral(double number,
+ int pos) {
+ return PreParserExpression::Default();
+ }
};
@@ -637,7 +665,11 @@
// Return types for traversing functions.
typedef PreParserIdentifier Identifier;
typedef PreParserExpression Expression;
+ typedef PreParserExpression FunctionLiteral;
+ typedef PreParserExpression ObjectLiteralProperty;
+ typedef PreParserExpression Literal;
typedef PreParserExpressionList ExpressionList;
+ typedef PreParserExpressionList PropertyList;
};
explicit PreParserTraits(PreParser* pre_parser) : pre_parser_(pre_parser) {}
@@ -654,6 +686,23 @@
return identifier.IsEvalOrArguments();
}
+ static bool IsBoilerplateProperty(PreParserExpression property) {
+ // PreParser doesn't count boilerplate properties.
+ return false;
+ }
+
+ static bool IsArrayIndex(PreParserIdentifier string, uint32_t* index) {
+ return false;
+ }
+
+ static void PushLiteralName(FuncNameInferrer* fni, PreParserIdentifier id) {
+ // PreParser should not use FuncNameInferrer.
+ ASSERT(false);
+ }
+
+ static void CheckFunctionLiteralInsideTopLevelObjectLiteral(
+ PreParserScope* scope, PreParserExpression value, bool* has_function) {}
+
// Reporting errors.
void ReportMessageAt(Scanner::Location location,
const char* message,
@@ -673,6 +722,12 @@
static PreParserExpression EmptyExpression() {
return PreParserExpression::Default();
}
+ static PreParserExpression EmptyLiteral() {
+ return PreParserExpression::Default();
+ }
+ static PreParserExpressionList NullExpressionList() {
+ return PreParserExpressionList();
+ }
// Odd-ball literal creators.
static PreParserExpression GetLiteralTheHole(int position,
@@ -712,10 +767,21 @@
return PreParserExpressionList();
}
+ static PreParserExpressionList NewPropertyList(int size, void* zone) {
+ return PreParserExpressionList();
+ }
+
// Temporary glue; these functions will move to ParserBase.
PreParserExpression ParseAssignmentExpression(bool accept_IN, bool* ok);
- PreParserExpression ParseObjectLiteral(bool* ok);
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,
+ bool* ok);
private:
PreParser* pre_parser_;
@@ -763,7 +829,7 @@
if (stack_overflow()) return kPreParseStackOverflow;
if (!ok) {
ReportUnexpectedToken(scanner()->current_token());
- } else if (!scope_->is_classic_mode()) {
+ } else if (scope_->strict_mode() == STRICT) {
CheckOctalLiteral(start_position, scanner()->location().end_pos, &ok);
}
return kPreParseSuccess;
@@ -777,7 +843,7 @@
// keyword and parameters, and have consumed the initial '{'.
// At return, unless an error occurred, the scanner is positioned before the
// the final '}'.
- PreParseResult PreParseLazyFunction(LanguageMode mode,
+ PreParseResult PreParseLazyFunction(StrictMode strict_mode,
bool is_generator,
ParserRecorder* log);
@@ -852,8 +918,6 @@
kUnknownSourceElements
};
- typedef int Arguments;
-
// All ParseXXX functions take as the last argument an *ok parameter
// which is set to false if parsing failed; it is unchanged otherwise.
// By making the 'exception handling' explicit, we are forced to check
@@ -897,7 +961,6 @@
Expression ParseObjectLiteral(bool* ok);
Expression ParseV8Intrinsic(bool* ok);
- Arguments ParseArguments(bool* ok);
Expression ParseFunctionLiteral(
Identifier name,
Scanner::Location function_name_location,
@@ -975,9 +1038,8 @@
return ReportMessageAt(source_location, "unexpected_reserved");
case Token::YIELD:
case Token::FUTURE_STRICT_RESERVED_WORD:
- return ReportMessageAt(source_location,
- is_classic_mode() ? "unexpected_token_identifier"
- : "unexpected_strict_reserved");
+ return ReportMessageAt(source_location, strict_mode() == SLOPPY
+ ? "unexpected_token_identifier" : "unexpected_strict_reserved");
default:
const char* name = Token::String(token);
ASSERT(name != NULL);
@@ -995,13 +1057,14 @@
if (next == Token::IDENTIFIER) {
typename Traits::Type::Identifier name = this->GetSymbol(scanner());
if (allow_eval_or_arguments == kDontAllowEvalOrArguments &&
- !is_classic_mode() && this->IsEvalOrArguments(name)) {
+ strict_mode() == STRICT && this->IsEvalOrArguments(name)) {
ReportMessageAt(scanner()->location(), "strict_eval_arguments");
*ok = false;
}
return name;
- } else if (is_classic_mode() && (next == Token::FUTURE_STRICT_RESERVED_WORD ||
- (next == Token::YIELD && !is_generator()))) {
+ } else if (strict_mode() == SLOPPY &&
+ (next == Token::FUTURE_STRICT_RESERVED_WORD ||
+ (next == Token::YIELD && !is_generator()))) {
return this->GetSymbol(scanner());
} else {
this->ReportUnexpectedToken(next);
@@ -1095,6 +1158,13 @@
#define DUMMY ) // to make indentation work
#undef DUMMY
+// Used in functions where the return type is not Traits::Type::Expression.
+#define CHECK_OK_CUSTOM(x) ok); \
+ if (!*ok) return this->x(); \
+ ((void)0
+#define DUMMY ) // to make indentation work
+#undef DUMMY
+
template <class Traits>
typename Traits::Type::Expression ParserBase<Traits>::ParsePrimaryExpression(
bool* ok) {
@@ -1240,7 +1310,204 @@
return factory()->NewArrayLiteral(values, literal_index, pos);
}
+
+template <class Traits>
+typename Traits::Type::Expression ParserBase<Traits>::ParseObjectLiteral(
+ bool* ok) {
+ // ObjectLiteral ::
+ // '{' ((
+ // ((IdentifierName | String | Number) ':' AssignmentExpression) |
+ // (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
+ // ) ',')* '}'
+ // (Except that trailing comma is not required and not allowed.)
+
+ int pos = peek_position();
+ typename Traits::Type::PropertyList properties =
+ this->NewPropertyList(4, zone_);
+ int number_of_boilerplate_properties = 0;
+ bool has_function = false;
+
+ ObjectLiteralChecker checker(this, strict_mode());
+
+ Expect(Token::LBRACE, CHECK_OK);
+
+ while (peek() != Token::RBRACE) {
+ if (fni_ != NULL) fni_->Enter();
+
+ typename Traits::Type::Literal key = this->EmptyLiteral();
+ Token::Value next = peek();
+ int next_pos = peek_position();
+
+ switch (next) {
+ case Token::FUTURE_RESERVED_WORD:
+ case Token::FUTURE_STRICT_RESERVED_WORD:
+ case Token::IDENTIFIER: {
+ bool is_getter = false;
+ bool is_setter = false;
+ typename Traits::Type::Identifier id =
+ ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
+ if (fni_ != NULL) this->PushLiteralName(fni_, id);
+
+ 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.
+ Token::Value next = Next();
+ if (next != i::Token::IDENTIFIER &&
+ next != i::Token::FUTURE_RESERVED_WORD &&
+ next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
+ next != i::Token::NUMBER &&
+ next != i::Token::STRING &&
+ !Token::IsKeyword(next)) {
+ ReportUnexpectedToken(next);
+ *ok = false;
+ return this->EmptyLiteral();
+ }
+ // Validate the property.
+ PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
+ checker.CheckProperty(next, type, CHECK_OK);
+ typename Traits::Type::Identifier name = this->GetSymbol(scanner_);
+ 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,
+ CHECK_OK);
+ // Allow any number of parameters for compatibilty with JSC.
+ // Specification only allows zero parameters for get and one for set.
+ typename Traits::Type::ObjectLiteralProperty property =
+ factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
+ if (this->IsBoilerplateProperty(property)) {
+ number_of_boilerplate_properties++;
+ }
+ properties->Add(property, zone());
+ if (peek() != Token::RBRACE) {
+ // Need {} because of the CHECK_OK macro.
+ Expect(Token::COMMA, CHECK_OK);
+ }
+
+ if (fni_ != NULL) {
+ fni_->Infer();
+ fni_->Leave();
+ }
+ continue; // restart the while
+ }
+ // 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()->NewLiteral(id, next_pos);
+ break;
+ }
+ case Token::STRING: {
+ Consume(Token::STRING);
+ typename Traits::Type::Identifier 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()->NewLiteral(string, next_pos);
+ break;
+ }
+ case Token::NUMBER: {
+ Consume(Token::NUMBER);
+ key = this->ExpressionFromLiteral(Token::NUMBER, next_pos, scanner_,
+ factory());
+ break;
+ }
+ default:
+ if (Token::IsKeyword(next)) {
+ Consume(next);
+ typename Traits::Type::Identifier string = this->GetSymbol(scanner_);
+ key = factory()->NewLiteral(string, next_pos);
+ } else {
+ Token::Value next = Next();
+ ReportUnexpectedToken(next);
+ *ok = false;
+ return this->EmptyLiteral();
+ }
+ }
+
+ // Validate the property
+ checker.CheckProperty(next, kValueProperty, CHECK_OK);
+
+ Expect(Token::COLON, CHECK_OK);
+ typename Traits::Type::Expression value =
+ this->ParseAssignmentExpression(true, CHECK_OK);
+
+ typename Traits::Type::ObjectLiteralProperty property =
+ factory()->NewObjectLiteralProperty(key, value);
+
+ // Mark top-level object literals that contain function literals and
+ // pretenure the literal so it can be added as a constant function
+ // property. (Parser only.)
+ this->CheckFunctionLiteralInsideTopLevelObjectLiteral(scope_, value,
+ &has_function);
+
+ // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
+ if (this->IsBoilerplateProperty(property)) {
+ number_of_boilerplate_properties++;
+ }
+ properties->Add(property, zone());
+
+ // TODO(1240767): Consider allowing trailing comma.
+ if (peek() != Token::RBRACE) {
+ // Need {} because of the CHECK_OK macro.
+ Expect(Token::COMMA, CHECK_OK);
+ }
+
+ if (fni_ != NULL) {
+ fni_->Infer();
+ fni_->Leave();
+ }
+ }
+ Expect(Token::RBRACE, CHECK_OK);
+
+ // Computation of literal_index must happen before pre parse bailout.
+ int literal_index = function_state_->NextMaterializedLiteralIndex();
+
+ return factory()->NewObjectLiteral(properties,
+ literal_index,
+ number_of_boilerplate_properties,
+ has_function,
+ pos);
+}
+
+
+template <class Traits>
+typename Traits::Type::ExpressionList ParserBase<Traits>::ParseArguments(
+ bool* ok) {
+ // Arguments ::
+ // '(' (AssignmentExpression)*[','] ')'
+
+ typename Traits::Type::ExpressionList result =
+ this->NewExpressionList(4, zone_);
+ Expect(Token::LPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+ bool done = (peek() == Token::RPAREN);
+ while (!done) {
+ typename Traits::Type::Expression argument =
+ this->ParseAssignmentExpression(true,
+ CHECK_OK_CUSTOM(NullExpressionList));
+ result->Add(argument, zone_);
+ if (result->length() > Code::kMaxArguments) {
+ ReportMessageAt(scanner()->location(), "too_many_arguments");
+ *ok = false;
+ return this->NullExpressionList();
+ }
+ done = (peek() == Token::RPAREN);
+ if (!done) {
+ // Need {} because of the CHECK_OK_CUSTOM macro.
+ Expect(Token::COMMA, CHECK_OK_CUSTOM(NullExpressionList));
+ }
+ }
+ Expect(Token::RPAREN, CHECK_OK_CUSTOM(NullExpressionList));
+ return result;
+}
+
+
#undef CHECK_OK
+#undef CHECK_OK_CUSTOM
template <typename Traits>
@@ -1260,7 +1527,7 @@
if (HasConflict(old_type, type)) {
if (IsDataDataConflict(old_type, type)) {
// Both are data properties.
- if (language_mode_ == CLASSIC_MODE) return;
+ if (strict_mode_ == SLOPPY) return;
parser()->ReportMessageAt(scanner()->location(),
"strict_duplicate_property");
} else if (IsDataAccessorConflict(old_type, type)) {
diff --git a/src/promise.js b/src/promise.js
index 2c36d4d..8e22c31 100644
--- a/src/promise.js
+++ b/src/promise.js
@@ -102,6 +102,15 @@
}
+// For API.
+
+function PromiseNopResolver() {}
+
+function PromiseCreate() {
+ return new Promise(PromiseNopResolver)
+}
+
+
// Convenience.
function PromiseDeferred() {
@@ -217,7 +226,7 @@
PromiseCoerce.table = new $WeakMap;
function PromiseCoerce(constructor, x) {
- if (!(IsPromise(x) || IS_NULL_OR_UNDEFINED(x))) {
+ if (!IsPromise(x) && IS_SPEC_OBJECT(x)) {
var then = x.then;
if (typeof then === 'function') {
if (PromiseCoerce.table.has(x)) {
diff --git a/src/property-details-inl.h b/src/property-details-inl.h
new file mode 100644
index 0000000..98eb1cf
--- /dev/null
+++ b/src/property-details-inl.h
@@ -0,0 +1,51 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_PROPERTY_DETAILS_INL_H_
+#define V8_PROPERTY_DETAILS_INL_H_
+
+#include "objects.h"
+#include "property-details.h"
+#include "v8conversions.h"
+
+namespace v8 {
+namespace internal {
+
+inline bool Representation::CanContainDouble(double value) {
+ if (IsDouble() || is_more_general_than(Representation::Double())) {
+ return true;
+ }
+ if (IsInt32Double(value)) {
+ if (IsInteger32()) return true;
+ if (IsSmi()) return Smi::IsValid(static_cast<int32_t>(value));
+ }
+ return false;
+}
+
+} } // namespace v8::internal
+
+#endif // V8_PROPERTY_DETAILS_INL_H_
diff --git a/src/property-details.h b/src/property-details.h
index 3405bd9..01050db 100644
--- a/src/property-details.h
+++ b/src/property-details.h
@@ -148,6 +148,8 @@
return other.is_more_general_than(*this) || other.Equals(*this);
}
+ bool CanContainDouble(double value);
+
Representation generalize(Representation other) {
if (other.fits_into(*this)) return *this;
if (other.is_more_general_than(*this)) return other;
diff --git a/src/runtime.cc b/src/runtime.cc
index aa75688..140c323 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -153,25 +153,13 @@
PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
-// Assert that the given argument has a valid value for a StrictModeFlag
-// and store it in a StrictModeFlag variable with the given name.
+// Assert that the given argument has a valid value for a StrictMode
+// and store it in a StrictMode variable with the given name.
#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \
RUNTIME_ASSERT(args[index]->IsSmi()); \
- RUNTIME_ASSERT(args.smi_at(index) == kStrictMode || \
- args.smi_at(index) == kNonStrictMode); \
- StrictModeFlag name = \
- static_cast<StrictModeFlag>(args.smi_at(index));
-
-
-// Assert that the given argument has a valid value for a LanguageMode
-// and store it in a LanguageMode variable with the given name.
-#define CONVERT_LANGUAGE_MODE_ARG(name, index) \
- ASSERT(args[index]->IsSmi()); \
- ASSERT(args.smi_at(index) == CLASSIC_MODE || \
- args.smi_at(index) == STRICT_MODE || \
- args.smi_at(index) == EXTENDED_MODE); \
- LanguageMode name = \
- static_cast<LanguageMode>(args.smi_at(index));
+ RUNTIME_ASSERT(args.smi_at(index) == STRICT || \
+ args.smi_at(index) == SLOPPY); \
+ StrictMode name = static_cast<StrictMode>(args.smi_at(index));
static Handle<Map> ComputeObjectLiteralMap(
@@ -298,7 +286,7 @@
if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
// Array index as string (uint32).
result = JSObject::SetOwnElement(
- boilerplate, element_index, value, kNonStrictMode);
+ boilerplate, element_index, value, SLOPPY);
} else {
Handle<String> name(String::cast(*key));
ASSERT(!name->AsArrayIndex(&element_index));
@@ -309,7 +297,7 @@
} else if (key->ToArrayIndex(&element_index)) {
// Array index (uint32).
result = JSObject::SetOwnElement(
- boilerplate, element_index, value, kNonStrictMode);
+ boilerplate, element_index, value, SLOPPY);
} else {
// Non-uint32 number.
ASSERT(key->IsNumber());
@@ -2099,7 +2087,7 @@
attr |= READ_ONLY;
}
- LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
+ StrictMode strict_mode = DeclareGlobalsStrictMode::decode(flags);
if (!lookup.IsFound() || is_function) {
// If the local property exists, check that we can reconfigure it
@@ -2121,7 +2109,7 @@
RETURN_IF_EMPTY_HANDLE(isolate,
JSObject::SetProperty(
global, name, value, static_cast<PropertyAttributes>(attr),
- language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
+ strict_mode));
}
}
@@ -2177,8 +2165,7 @@
Handle<JSObject> object = Handle<JSObject>::cast(holder);
RETURN_IF_EMPTY_HANDLE(
isolate,
- JSReceiver::SetProperty(object, name, initial_value, mode,
- kNonStrictMode));
+ JSReceiver::SetProperty(object, name, initial_value, mode, SLOPPY));
}
}
@@ -2224,7 +2211,7 @@
JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
} else {
RETURN_IF_EMPTY_HANDLE(isolate,
- JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
+ JSReceiver::SetProperty(object, name, value, mode, SLOPPY));
}
}
@@ -2245,9 +2232,7 @@
CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
RUNTIME_ASSERT(args[1]->IsSmi());
- CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
- StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
+ CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 1);
// According to ECMA-262, section 12.2, page 62, the property must
// not be deletable.
@@ -2271,7 +2256,7 @@
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Handle<Object> result = JSObject::SetPropertyForResult(
handle(lookup.holder()), &lookup, name, value, attributes,
- strict_mode_flag);
+ strict_mode);
RETURN_IF_EMPTY_HANDLE(isolate, result);
return *result;
} else {
@@ -2284,7 +2269,7 @@
CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
Handle<GlobalObject> global(isolate->context()->global_object());
Handle<Object> result = JSReceiver::SetProperty(
- global, name, value, attributes, strict_mode_flag);
+ global, name, value, attributes, strict_mode);
RETURN_IF_EMPTY_HANDLE(isolate, result);
return *result;
}
@@ -2335,11 +2320,10 @@
// BUG 1213575: Handle the case where we have to set a read-only
// property through an interceptor and only do it if it's
// uninitialized, e.g. the hole. Nirk...
- // Passing non-strict mode because the property is writable.
+ // Passing sloppy mode because the property is writable.
RETURN_IF_EMPTY_HANDLE(
isolate,
- JSReceiver::SetProperty(global, name, value, attributes,
- kNonStrictMode));
+ JSReceiver::SetProperty(global, name, value, attributes, SLOPPY));
return *value;
}
@@ -2409,7 +2393,7 @@
// Strict mode not needed (const disallowed in strict mode).
RETURN_IF_EMPTY_HANDLE(
isolate,
- JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
+ JSReceiver::SetProperty(global, name, value, NONE, SLOPPY));
return *value;
}
@@ -2460,8 +2444,7 @@
// Strict mode not needed (const disallowed in strict mode).
RETURN_IF_EMPTY_HANDLE(
isolate,
- JSReceiver::SetProperty(object, name, value, attributes,
- kNonStrictMode));
+ JSReceiver::SetProperty(object, name, value, attributes, SLOPPY));
}
}
@@ -2621,7 +2604,7 @@
code,
false);
optimized->shared()->DontAdaptArguments();
- JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
+ JSReceiver::SetProperty(holder, key, optimized, NONE, STRICT);
return optimized;
}
@@ -2643,7 +2626,7 @@
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_IsSloppyModeFunction) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
@@ -2657,7 +2640,7 @@
}
JSFunction* function = JSFunction::cast(callable);
SharedFunctionInfo* shared = function->shared();
- return isolate->heap()->ToBoolean(shared->is_classic_mode());
+ return isolate->heap()->ToBoolean(shared->strict_mode() == SLOPPY);
}
@@ -2677,7 +2660,7 @@
JSFunction* function = JSFunction::cast(callable);
SharedFunctionInfo* shared = function->shared();
- if (shared->native() || !shared->is_classic_mode()) {
+ if (shared->native() || shared->strict_mode() == STRICT) {
return isolate->heap()->undefined_value();
}
// Returns undefined for strict or native functions, or
@@ -5082,7 +5065,7 @@
name,
obj_value,
handle(lookup.holder()),
- kStrictMode);
+ STRICT);
RETURN_IF_EMPTY_HANDLE(isolate, result_object);
return *result_object;
}
@@ -5155,7 +5138,7 @@
Handle<Object> key,
Handle<Object> value,
PropertyAttributes attr,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
if (object->IsUndefined() || object->IsNull()) {
@@ -5273,7 +5256,7 @@
return value;
}
- return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
+ return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
false,
DEFINE_PROPERTY);
}
@@ -5281,7 +5264,7 @@
if (key->IsName()) {
Handle<Name> name = Handle<Name>::cast(key);
if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
+ return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
false,
DEFINE_PROPERTY);
} else {
@@ -5299,7 +5282,7 @@
Handle<String> name = Handle<String>::cast(converted);
if (name->AsArrayIndex(&index)) {
- return JSObject::SetElement(js_object, index, value, attr, kNonStrictMode,
+ return JSObject::SetElement(js_object, index, value, attr, SLOPPY,
false,
DEFINE_PROPERTY);
} else {
@@ -5377,10 +5360,10 @@
PropertyAttributes attributes =
static_cast<PropertyAttributes>(unchecked_attributes);
- StrictModeFlag strict_mode = kNonStrictMode;
+ StrictMode strict_mode = SLOPPY;
if (args.length() == 5) {
- CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
- strict_mode = strict_mode_flag;
+ CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_arg, 4);
+ strict_mode = strict_mode_arg;
}
Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
@@ -5559,7 +5542,7 @@
CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
- JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
+ JSReceiver::DeleteMode delete_mode = strict_mode == STRICT
? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
RETURN_IF_EMPTY_HANDLE(isolate, result);
@@ -5811,7 +5794,9 @@
}
}
next_copy_index += local_property_count[i];
- if (jsproto->HasHiddenProperties()) {
+
+ // Hidden properties only show up if the filter does not skip strings.
+ if ((filter & STRING) == 0 && jsproto->HasHiddenProperties()) {
hidden_strings++;
}
if (i < length - 1) {
@@ -6002,7 +5987,7 @@
if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
if (key->Equals(isolate->heap()->callee_string())) {
JSFunction* function = frame->function();
- if (!function->shared()->is_classic_mode()) {
+ if (function->shared()->strict_mode() == STRICT) {
return isolate->Throw(*isolate->factory()->NewTypeError(
"strict_arguments_callee", HandleVector<Object>(NULL, 0)));
}
@@ -7914,11 +7899,11 @@
Handle<FixedArray> parameter_map =
isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
parameter_map->set_map(
- isolate->heap()->non_strict_arguments_elements_map());
+ isolate->heap()->sloppy_arguments_elements_map());
Handle<Map> old_map(result->map());
Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
- new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
+ new_map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS);
result->set_map(*new_map);
result->set_elements(*parameter_map);
@@ -8735,7 +8720,9 @@
PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- function->ReplaceCode(function->shared()->code());
+ if (!function->IsOptimized()) {
+ function->ReplaceCode(function->shared()->code());
+ }
return NULL;
}
@@ -9049,7 +9036,7 @@
case VAR:
case LET:
case CONST:
- case CONST_HARMONY: {
+ case CONST_LEGACY: {
PropertyAttributes attr =
IsImmutableVariableMode(mode) ? FROZEN : SEALED;
Handle<AccessorInfo> info =
@@ -9062,7 +9049,7 @@
case MODULE: {
Object* referenced_context = Context::cast(host_context)->get(index);
Handle<JSModule> value(Context::cast(referenced_context)->module());
- JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
+ JSReceiver::SetProperty(module, name, value, FROZEN, STRICT);
break;
}
case INTERNAL:
@@ -9285,9 +9272,7 @@
Handle<Object> value(args[0], isolate);
CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
- CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
- StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
+ CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 3);
int index;
PropertyAttributes attributes;
@@ -9314,7 +9299,7 @@
if ((attributes & READ_ONLY) == 0) {
// Context is a fixed array and set cannot fail.
context->set(index, *value);
- } else if (strict_mode == kStrictMode) {
+ } else if (strict_mode == STRICT) {
// Setting read only property in strict mode.
Handle<Object> error =
isolate->factory()->NewTypeError("strict_cannot_assign",
@@ -9336,14 +9321,14 @@
// The property was not found.
ASSERT(attributes == ABSENT);
- if (strict_mode == kStrictMode) {
+ if (strict_mode == STRICT) {
// Throw in strict mode (assignment to undefined variable).
Handle<Object> error =
isolate->factory()->NewReferenceError(
"not_defined", HandleVector(&name, 1));
return isolate->Throw(*error);
}
- // In non-strict mode, the property is added to the global object.
+ // In sloppy mode, the property is added to the global object.
attributes = NONE;
object = Handle<JSReceiver>(isolate->context()->global_object());
}
@@ -9354,7 +9339,7 @@
RETURN_IF_EMPTY_HANDLE(
isolate,
JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
- } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
+ } else if (strict_mode == STRICT && (attributes & READ_ONLY) != 0) {
// Setting read only property in strict mode.
Handle<Object> error =
isolate->factory()->NewTypeError(
@@ -9612,6 +9597,28 @@
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCacheVersion) {
+ HandleScope hs(isolate);
+ ASSERT(args.length() == 0);
+ if (!isolate->eternal_handles()->Exists(EternalHandles::DATE_CACHE_VERSION)) {
+ Handle<FixedArray> date_cache_version =
+ isolate->factory()->NewFixedArray(1, TENURED);
+ date_cache_version->set(0, Smi::FromInt(0));
+ isolate->eternal_handles()->CreateSingleton(
+ isolate, *date_cache_version, EternalHandles::DATE_CACHE_VERSION);
+ }
+ Handle<FixedArray> date_cache_version =
+ Handle<FixedArray>::cast(isolate->eternal_handles()->GetSingleton(
+ EternalHandles::DATE_CACHE_VERSION));
+ // Return result as a JS array.
+ Handle<JSObject> result =
+ isolate->factory()->NewJSObject(isolate->array_function());
+ isolate->factory()->SetContent(Handle<JSArray>::cast(result),
+ date_cache_version);
+ return *result;
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
SealHandleScope shs(isolate);
ASSERT(args.length() == 1);
@@ -9693,7 +9700,7 @@
ParseRestriction restriction = function_literal_only
? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
Handle<JSFunction> fun = Compiler::GetFunctionFromEval(
- source, context, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
+ source, context, SLOPPY, restriction, RelocInfo::kNoPosition);
RETURN_IF_EMPTY_HANDLE(isolate, fun);
return *fun;
}
@@ -9702,7 +9709,7 @@
static ObjectPair CompileGlobalEval(Isolate* isolate,
Handle<String> source,
Handle<Object> receiver,
- LanguageMode language_mode,
+ StrictMode strict_mode,
int scope_position) {
Handle<Context> context = Handle<Context>(isolate->context());
Handle<Context> native_context = Handle<Context>(context->native_context());
@@ -9722,7 +9729,7 @@
// and return the compiled function bound in the local context.
static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
Handle<JSFunction> compiled = Compiler::GetFunctionFromEval(
- source, context, language_mode, restriction, scope_position);
+ source, context, strict_mode, restriction, scope_position);
RETURN_IF_EMPTY_HANDLE_VALUE(isolate, compiled,
MakePair(Failure::Exception(), NULL));
return MakePair(*compiled, *receiver);
@@ -9745,12 +9752,14 @@
return MakePair(*callee, isolate->heap()->undefined_value());
}
- CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
+ ASSERT(args[3]->IsSmi());
+ ASSERT(args.smi_at(3) == SLOPPY || args.smi_at(3) == STRICT);
+ StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(3));
ASSERT(args[4]->IsSmi());
return CompileGlobalEval(isolate,
args.at<String>(1),
args.at<Object>(2),
- language_mode,
+ strict_mode,
args.smi_at(4));
}
@@ -9815,7 +9824,7 @@
// Strict not needed. Used for cycle detection in Array join implementation.
RETURN_IF_EMPTY_HANDLE(isolate, JSObject::SetFastElement(array, length,
element,
- kNonStrictMode,
+ SLOPPY,
true));
return isolate->heap()->true_value();
}
@@ -10000,7 +10009,7 @@
}
break;
}
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
case EXTERNAL_##TYPE##_ELEMENTS: \
case TYPE##_ELEMENTS: \
@@ -11287,7 +11296,7 @@
// THE FRAME ITERATOR TO WRAP THE RECEIVER.
Handle<Object> receiver(it.frame()->receiver(), isolate);
if (!receiver->IsJSObject() &&
- shared->is_classic_mode() &&
+ shared->strict_mode() == SLOPPY &&
!function->IsBuiltin()) {
// If the receiver is not a JSObject and the function is not a
// builtin or strict-mode we have hit an optimization where a
@@ -11339,8 +11348,7 @@
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
- Runtime::SetObjectProperty(
- isolate, target, name, value, NONE, kNonStrictMode),
+ Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
Handle<JSObject>());
}
@@ -11352,8 +11360,7 @@
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
- Runtime::SetObjectProperty(
- isolate, target, name, value, NONE, kNonStrictMode),
+ Runtime::SetObjectProperty(isolate, target, name, value, NONE, SLOPPY),
Handle<JSObject>());
}
@@ -11436,7 +11443,7 @@
key,
GetProperty(isolate, ext, key),
NONE,
- kNonStrictMode),
+ SLOPPY),
Handle<JSObject>());
}
}
@@ -11537,8 +11544,7 @@
// We don't expect this to do anything except replacing
// property value.
Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
- NONE,
- kNonStrictMode);
+ NONE, SLOPPY);
return true;
}
}
@@ -11586,8 +11592,7 @@
isolate,
Runtime::SetObjectProperty(isolate, closure_scope, key,
GetProperty(isolate, ext, key),
- NONE,
- kNonStrictMode),
+ NONE, SLOPPY),
Handle<JSObject>());
}
}
@@ -11619,8 +11624,7 @@
if (JSReceiver::HasProperty(ext, variable_name)) {
// We don't expect this to do anything except replacing property value.
Runtime::SetObjectProperty(isolate, ext, variable_name, new_value,
- NONE,
- kNonStrictMode);
+ NONE, SLOPPY);
return true;
}
}
@@ -11642,8 +11646,7 @@
RETURN_IF_EMPTY_HANDLE_VALUE(
isolate,
Runtime::SetObjectProperty(isolate, catch_scope, name, thrown_object,
- NONE,
- kNonStrictMode),
+ NONE, SLOPPY),
Handle<JSObject>());
return catch_scope;
}
@@ -12156,7 +12159,7 @@
Smi* position_value = Smi::FromInt(break_location_iterator.position());
JSObject::SetElement(array, len,
Handle<Object>(position_value, isolate),
- NONE, kNonStrictMode);
+ NONE, SLOPPY);
len++;
}
}
@@ -12711,7 +12714,7 @@
isolate->factory()->arguments_string(),
arguments,
::NONE,
- kNonStrictMode);
+ SLOPPY);
return target;
}
@@ -12731,7 +12734,7 @@
Handle<JSFunction> eval_fun =
Compiler::GetFunctionFromEval(source,
context,
- CLASSIC_MODE,
+ SLOPPY,
NO_PARSE_RESTRICTION,
RelocInfo::kNoPosition);
RETURN_IF_EMPTY_HANDLE(isolate, eval_fun);
@@ -12989,7 +12992,7 @@
// Get the constructor function for context extension and arguments array.
JSObject* arguments_boilerplate =
- isolate->context()->native_context()->arguments_boilerplate();
+ isolate->context()->native_context()->sloppy_arguments_boilerplate();
JSFunction* arguments_function =
JSFunction::cast(arguments_boilerplate->map()->constructor());
@@ -14577,7 +14580,7 @@
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
-ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
+ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
// Properties test sitting with elements tests - not fooling anyone.
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
diff --git a/src/runtime.h b/src/runtime.h
index d770968..99c575f 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -64,7 +64,7 @@
F(ToFastProperties, 1, 1) \
F(FinishArrayPrototypeSetup, 1, 1) \
F(SpecialArrayFunctions, 1, 1) \
- F(IsClassicModeFunction, 1, 1) \
+ F(IsSloppyModeFunction, 1, 1) \
F(GetDefaultReceiver, 1, 1) \
\
F(GetPrototype, 1, 1) \
@@ -257,6 +257,7 @@
F(DateToUTC, 1, 1) \
F(DateMakeDay, 2, 1) \
F(DateSetValue, 3, 1) \
+ F(DateCacheVersion, 0, 1) \
\
/* Numbers */ \
\
@@ -302,7 +303,7 @@
/* ES5 */ \
F(ObjectFreeze, 1, 1) \
\
- /* Harmony Microtasks */ \
+ /* Harmony microtasks */ \
F(GetMicrotaskState, 0, 1) \
\
/* Harmony modules */ \
@@ -455,7 +456,7 @@
F(HasFastDoubleElements, 1, 1) \
F(HasFastHoleyElements, 1, 1) \
F(HasDictionaryElements, 1, 1) \
- F(HasNonStrictArgumentsElements, 1, 1) \
+ F(HasSloppyArgumentsElements, 1, 1) \
F(HasExternalUint8ClampedElements, 1, 1) \
F(HasExternalArrayElements, 1, 1) \
F(HasExternalInt8Elements, 1, 1) \
@@ -785,7 +786,7 @@
Handle<Object> key,
Handle<Object> value,
PropertyAttributes attr,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
static Handle<Object> ForceSetObjectProperty(
Isolate* isolate,
@@ -861,12 +862,12 @@
//---------------------------------------------------------------------------
// Constants used by interface to runtime functions.
-class AllocateDoubleAlignFlag: public BitField<bool, 0, 1> {};
-class AllocateTargetSpace: public BitField<AllocationSpace, 1, 3> {};
+class AllocateDoubleAlignFlag: public BitField<bool, 0, 1> {};
+class AllocateTargetSpace: public BitField<AllocationSpace, 1, 3> {};
-class DeclareGlobalsEvalFlag: public BitField<bool, 0, 1> {};
-class DeclareGlobalsNativeFlag: public BitField<bool, 1, 1> {};
-class DeclareGlobalsLanguageMode: public BitField<LanguageMode, 2, 2> {};
+class DeclareGlobalsEvalFlag: public BitField<bool, 0, 1> {};
+class DeclareGlobalsNativeFlag: public BitField<bool, 1, 1> {};
+class DeclareGlobalsStrictMode: public BitField<StrictMode, 2, 1> {};
} } // namespace v8::internal
diff --git a/src/safepoint-table.h b/src/safepoint-table.h
index ea35253..cd094c5 100644
--- a/src/safepoint-table.h
+++ b/src/safepoint-table.h
@@ -219,6 +219,9 @@
// Record deoptimization index for lazy deoptimization for the last
// outstanding safepoints.
void RecordLazyDeoptimizationIndex(int index);
+ void BumpLastLazySafepointIndex() {
+ last_lazy_safepoint_ = deopt_index_list_.length();
+ }
// Emit the safepoint table after the body. The number of bits per
// entry must be enough to hold all the pointer indexes.
diff --git a/src/scopeinfo.cc b/src/scopeinfo.cc
index 03e69bf..e2ae854 100644
--- a/src/scopeinfo.cc
+++ b/src/scopeinfo.cc
@@ -78,7 +78,7 @@
// Encode the flags.
int flags = ScopeTypeField::encode(scope->scope_type()) |
CallsEvalField::encode(scope->calls_eval()) |
- LanguageModeField::encode(scope->language_mode()) |
+ StrictModeField::encode(scope->strict_mode()) |
FunctionVariableField::encode(function_name_info) |
FunctionVariableMode::encode(function_variable_mode);
scope_info->SetFlags(flags);
@@ -164,8 +164,8 @@
}
-LanguageMode ScopeInfo::language_mode() {
- return length() > 0 ? LanguageModeField::decode(Flags()) : CLASSIC_MODE;
+StrictMode ScopeInfo::strict_mode() {
+ return length() > 0 ? StrictModeField::decode(Flags()) : SLOPPY;
}
@@ -378,7 +378,7 @@
Handle<String>(String::cast(scope_info->get(i))),
Handle<Object>(context->get(context_index), isolate),
::NONE,
- kNonStrictMode);
+ SLOPPY);
RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, false);
}
return true;
diff --git a/src/scopes.cc b/src/scopes.cc
index 650f57c..bcb6435 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -190,9 +190,8 @@
scope_contains_with_ = false;
scope_calls_eval_ = false;
// Inherit the strict mode from the parent scope.
- language_mode_ = (outer_scope != NULL)
- ? outer_scope->language_mode_ : CLASSIC_MODE;
- outer_scope_calls_non_strict_eval_ = false;
+ strict_mode_ = outer_scope != NULL ? outer_scope->strict_mode_ : SLOPPY;
+ outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false;
force_eager_compilation_ = false;
force_context_allocation_ = (outer_scope != NULL && !is_function_scope())
@@ -207,7 +206,7 @@
end_position_ = RelocInfo::kNoPosition;
if (!scope_info.is_null()) {
scope_calls_eval_ = scope_info->CallsEval();
- language_mode_ = scope_info->language_mode();
+ strict_mode_ = scope_info->strict_mode();
}
}
@@ -470,7 +469,7 @@
InitializationFlag init_flag,
Interface* interface) {
ASSERT(!already_resolved());
- // This function handles VAR and CONST modes. DYNAMIC variables are
+ // This function handles VAR, LET, and CONST modes. DYNAMIC variables are
// introduces during variable allocation, INTERNAL variables are allocated
// explicitly, and TEMPORARY variables are allocated via NewTemporary().
ASSERT(IsDeclaredVariableMode(mode));
@@ -643,13 +642,13 @@
bool Scope::AllocateVariables(CompilationInfo* info,
AstNodeFactory<AstNullVisitor>* factory) {
// 1) Propagate scope information.
- bool outer_scope_calls_non_strict_eval = false;
+ bool outer_scope_calls_sloppy_eval = false;
if (outer_scope_ != NULL) {
- outer_scope_calls_non_strict_eval =
- outer_scope_->outer_scope_calls_non_strict_eval() |
- outer_scope_->calls_non_strict_eval();
+ outer_scope_calls_sloppy_eval =
+ outer_scope_->outer_scope_calls_sloppy_eval() |
+ outer_scope_->calls_sloppy_eval();
}
- PropagateScopeInfo(outer_scope_calls_non_strict_eval);
+ PropagateScopeInfo(outer_scope_calls_sloppy_eval);
// 2) Allocate module instances.
if (FLAG_harmony_modules && (is_global_scope() || is_module_scope())) {
@@ -881,21 +880,14 @@
if (HasTrivialOuterContext()) {
Indent(n1, "// scope has trivial outer context\n");
}
- switch (language_mode()) {
- case CLASSIC_MODE:
- break;
- case STRICT_MODE:
- Indent(n1, "// strict mode scope\n");
- break;
- case EXTENDED_MODE:
- Indent(n1, "// extended mode scope\n");
- break;
+ if (strict_mode() == STRICT) {
+ Indent(n1, "// strict mode scope\n");
}
if (scope_inside_with_) Indent(n1, "// scope inside 'with'\n");
if (scope_contains_with_) Indent(n1, "// scope contains 'with'\n");
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
- if (outer_scope_calls_non_strict_eval_) {
- Indent(n1, "// outer scope calls 'eval' in non-strict context\n");
+ if (outer_scope_calls_sloppy_eval_) {
+ Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
}
if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
if (num_stack_slots_ > 0) { Indent(n1, "// ");
@@ -1017,9 +1009,9 @@
// object).
*binding_kind = DYNAMIC_LOOKUP;
return NULL;
- } else if (calls_non_strict_eval()) {
+ } else if (calls_sloppy_eval()) {
// A variable binding may have been found in an outer scope, but the current
- // scope makes a non-strict 'eval' call, so the found variable may not be
+ // scope makes a sloppy 'eval' call, so the found variable may not be
// the correct one (the 'eval' may introduce a binding with the same name).
// In that case, change the lookup result to reflect this situation.
if (*binding_kind == BOUND) {
@@ -1071,8 +1063,7 @@
break;
case UNBOUND_EVAL_SHADOWED:
- // No binding has been found. But some scope makes a
- // non-strict 'eval' call.
+ // No binding has been found. But some scope makes a sloppy 'eval' call.
var = NonLocal(proxy->name(), DYNAMIC_GLOBAL);
break;
@@ -1084,7 +1075,7 @@
ASSERT(var != NULL);
- if (FLAG_harmony_scoping && is_extended_mode() &&
+ if (FLAG_harmony_scoping && strict_mode() == STRICT &&
var->is_const_mode() && proxy->IsLValue()) {
// Assignment to const. Throw a syntax error.
MessageLocation location(
@@ -1123,7 +1114,7 @@
Isolate* isolate = info->isolate();
Factory* factory = isolate->factory();
Handle<JSArray> array = factory->NewJSArray(1);
- USE(JSObject::SetElement(array, 0, var->name(), NONE, kStrictMode));
+ USE(JSObject::SetElement(array, 0, var->name(), NONE, STRICT));
Handle<Object> result =
factory->NewSyntaxError("module_type_error", array);
isolate->Throw(*result, &location);
@@ -1157,16 +1148,16 @@
}
-bool Scope::PropagateScopeInfo(bool outer_scope_calls_non_strict_eval ) {
- if (outer_scope_calls_non_strict_eval) {
- outer_scope_calls_non_strict_eval_ = true;
+bool Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval ) {
+ if (outer_scope_calls_sloppy_eval) {
+ outer_scope_calls_sloppy_eval_ = true;
}
- bool calls_non_strict_eval =
- this->calls_non_strict_eval() || outer_scope_calls_non_strict_eval_;
+ bool calls_sloppy_eval =
+ this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
for (int i = 0; i < inner_scopes_.length(); i++) {
Scope* inner_scope = inner_scopes_[i];
- if (inner_scope->PropagateScopeInfo(calls_non_strict_eval)) {
+ if (inner_scope->PropagateScopeInfo(calls_sloppy_eval)) {
inner_scope_calls_eval_ = true;
}
if (inner_scope->force_eager_compilation_) {
@@ -1246,7 +1237,7 @@
Variable* arguments = LocalLookup(isolate_->factory()->arguments_string());
ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
- bool uses_nonstrict_arguments = false;
+ bool uses_sloppy_arguments = false;
if (MustAllocate(arguments) && !HasArgumentsParameter()) {
// 'arguments' is used. Unless there is also a parameter called
@@ -1265,7 +1256,7 @@
// In strict mode 'arguments' does not alias formal parameters.
// Therefore in strict mode we allocate parameters as if 'arguments'
// were not used.
- uses_nonstrict_arguments = is_classic_mode();
+ uses_sloppy_arguments = strict_mode() == SLOPPY;
}
// The same parameter may occur multiple times in the parameters_ list.
@@ -1275,7 +1266,7 @@
for (int i = params_.length() - 1; i >= 0; --i) {
Variable* var = params_[i];
ASSERT(var->scope() == this);
- if (uses_nonstrict_arguments) {
+ if (uses_sloppy_arguments) {
// Force context allocation of the parameter.
var->ForceContextAllocation();
}
diff --git a/src/scopes.h b/src/scopes.h
index 06aaa90..b0d8434 100644
--- a/src/scopes.h
+++ b/src/scopes.h
@@ -234,9 +234,7 @@
void RecordEvalCall() { if (!is_global_scope()) scope_calls_eval_ = true; }
// Set the strict mode flag (unless disabled by a global flag).
- void SetLanguageMode(LanguageMode language_mode) {
- language_mode_ = language_mode;
- }
+ void SetStrictMode(StrictMode strict_mode) { strict_mode_ = strict_mode; }
// Position in the source where this scope begins and ends.
//
@@ -293,23 +291,17 @@
return is_eval_scope() || is_function_scope() ||
is_module_scope() || is_global_scope();
}
- bool is_classic_mode() const {
- return language_mode() == CLASSIC_MODE;
- }
- bool is_extended_mode() const {
- return language_mode() == EXTENDED_MODE;
- }
- bool is_strict_or_extended_eval_scope() const {
- return is_eval_scope() && !is_classic_mode();
+ bool is_strict_eval_scope() const {
+ return is_eval_scope() && strict_mode_ == STRICT;
}
// Information about which scopes calls eval.
bool calls_eval() const { return scope_calls_eval_; }
- bool calls_non_strict_eval() {
- return scope_calls_eval_ && is_classic_mode();
+ bool calls_sloppy_eval() {
+ return scope_calls_eval_ && strict_mode_ == SLOPPY;
}
- bool outer_scope_calls_non_strict_eval() const {
- return outer_scope_calls_non_strict_eval_;
+ bool outer_scope_calls_sloppy_eval() const {
+ return outer_scope_calls_sloppy_eval_;
}
// Is this scope inside a with statement.
@@ -324,7 +316,7 @@
ScopeType scope_type() const { return scope_type_; }
// The language mode of this scope.
- LanguageMode language_mode() const { return language_mode_; }
+ StrictMode strict_mode() const { return strict_mode_; }
// The variable corresponding the 'this' value.
Variable* receiver() { return receiver_; }
@@ -493,14 +485,14 @@
// This scope or a nested catch scope or with scope contain an 'eval' call. At
// the 'eval' call site this scope is the declaration scope.
bool scope_calls_eval_;
- // The language mode of this scope.
- LanguageMode language_mode_;
+ // The strict mode of this scope.
+ StrictMode strict_mode_;
// Source positions.
int start_position_;
int end_position_;
// Computed via PropagateScopeInfo.
- bool outer_scope_calls_non_strict_eval_;
+ bool outer_scope_calls_sloppy_eval_;
bool inner_scope_calls_eval_;
bool force_eager_compilation_;
bool force_context_allocation_;
@@ -538,13 +530,13 @@
// The variable reference could be statically resolved to a variable binding
// which is returned. There is no 'with' statement between the reference and
// the binding and no scope between the reference scope (inclusive) and
- // binding scope (exclusive) makes a non-strict 'eval' call.
+ // binding scope (exclusive) makes a sloppy 'eval' call.
BOUND,
// The variable reference could be statically resolved to a variable binding
// which is returned. There is no 'with' statement between the reference and
// the binding, but some scope between the reference scope (inclusive) and
- // binding scope (exclusive) makes a non-strict 'eval' call, that might
+ // binding scope (exclusive) makes a sloppy 'eval' call, that might
// possibly introduce variable bindings shadowing the found one. Thus the
// found variable binding is just a guess.
BOUND_EVAL_SHADOWED,
@@ -553,13 +545,13 @@
// and thus should be considered referencing a global variable. NULL is
// returned. The variable reference is not inside any 'with' statement and
// no scope between the reference scope (inclusive) and global scope
- // (exclusive) makes a non-strict 'eval' call.
+ // (exclusive) makes a sloppy 'eval' call.
UNBOUND,
// The variable reference could not be statically resolved to any binding
// NULL is returned. The variable reference is not inside any 'with'
// statement, but some scope between the reference scope (inclusive) and
- // global scope (exclusive) makes a non-strict 'eval' call, that might
+ // global scope (exclusive) makes a sloppy 'eval' call, that might
// possibly introduce a variable binding. Thus the reference should be
// considered referencing a global variable unless it is shadowed by an
// 'eval' introduced binding.
@@ -591,7 +583,7 @@
AstNodeFactory<AstNullVisitor>* factory);
// Scope analysis.
- bool PropagateScopeInfo(bool outer_scope_calls_non_strict_eval);
+ bool PropagateScopeInfo(bool outer_scope_calls_sloppy_eval);
bool HasTrivialContext() const;
// Predicates.
diff --git a/src/serialize.cc b/src/serialize.cc
index 46975ce..30a05d5 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -1144,15 +1144,15 @@
// allocation point and write a pointer to it to the current object.
ALL_SPACES(kBackref, kPlain, kStartOfObject)
ALL_SPACES(kBackrefWithSkip, kPlain, kStartOfObject)
-#if V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || V8_OOL_CONSTANT_POOL
// Deserialize a new object from pointer found in code and write
- // a pointer to it to the current object. Required only for MIPS, and
- // omitted on the other architectures because it is fully unrolled and
- // would cause bloat.
+ // a pointer to it to the current object. Required only for MIPS or ARM
+ // with ool constant pool, and omitted on the other architectures because
+ // it is fully unrolled and would cause bloat.
ALL_SPACES(kNewObject, kFromCode, kStartOfObject)
// Find a recently deserialized code object using its offset from the
// current allocation point and write a pointer to it to the current
- // object. Required only for MIPS.
+ // object. Required only for MIPS or ARM with ool constant pool.
ALL_SPACES(kBackref, kFromCode, kStartOfObject)
ALL_SPACES(kBackrefWithSkip, kFromCode, kStartOfObject)
#endif
@@ -1373,12 +1373,11 @@
for (int i = 0; i < root_index_wave_front_; i++) {
Object* root = heap->roots_array_start()[i];
if (!root->IsSmi() && root == heap_object) {
-#if V8_TARGET_ARCH_MIPS
+#if defined(V8_TARGET_ARCH_MIPS) || V8_OOL_CONSTANT_POOL
if (from == kFromCode) {
// In order to avoid code bloat in the deserializer we don't have
// support for the encoding that specifies a particular root should
- // be written into the lui/ori instructions on MIPS. Therefore we
- // should not generate such serialization data for MIPS.
+ // be written from within code.
return kInvalidRootIndex;
}
#endif
@@ -1631,6 +1630,9 @@
void Serializer::ObjectSerializer::VisitEmbeddedPointer(RelocInfo* rinfo) {
+ // Out-of-line constant pool entries will be visited by the ConstantPoolArray.
+ if (FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool()) return;
+
int skip = OutputRawData(rinfo->target_address_address(),
kCanReturnSkipInsteadOfSkipping);
HowToCode how_to_code = rinfo->IsCodedSpecially() ? kFromCode : kPlain;
@@ -1676,6 +1678,9 @@
void Serializer::ObjectSerializer::VisitCodeTarget(RelocInfo* rinfo) {
+ // Out-of-line constant pool entries will be visited by the ConstantPoolArray.
+ if (FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool()) return;
+
int skip = OutputRawData(rinfo->target_address_address(),
kCanReturnSkipInsteadOfSkipping);
Code* object = Code::GetCodeFromTargetAddress(rinfo->target_address());
@@ -1693,6 +1698,9 @@
void Serializer::ObjectSerializer::VisitCell(RelocInfo* rinfo) {
+ // Out-of-line constant pool entries will be visited by the ConstantPoolArray.
+ if (FLAG_enable_ool_constant_pool && rinfo->IsInConstantPool()) return;
+
int skip = OutputRawData(rinfo->pc(), kCanReturnSkipInsteadOfSkipping);
Cell* object = Cell::cast(rinfo->target_cell());
serializer_->SerializeObject(object, kPlain, kInnerPointer, skip);
@@ -1738,7 +1746,9 @@
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
for (RelocIterator it(code, mode_mask); !it.done(); it.next()) {
- it.rinfo()->WipeOut();
+ if (!(FLAG_enable_ool_constant_pool && it.rinfo()->IsInConstantPool())) {
+ it.rinfo()->WipeOut();
+ }
}
}
diff --git a/src/stub-cache.cc b/src/stub-cache.cc
index 37562a9..52e7f4c 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -222,7 +222,7 @@
Handle<Code> StubCache::ComputeKeyedStoreElement(
Handle<Map> receiver_map,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
KeyedAccessStoreMode store_mode) {
ExtraICState extra_state =
KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode);
@@ -396,7 +396,7 @@
Handle<Code> StubCache::ComputeStoreElementPolymorphic(
MapHandleList* receiver_maps,
KeyedAccessStoreMode store_mode,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
ASSERT(store_mode == STANDARD_STORE ||
store_mode == STORE_AND_GROW_NO_TRANSITION ||
store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
@@ -722,7 +722,7 @@
Handle<Code> StubCompiler::CompileStoreGeneric(Code::Flags flags) {
ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
- StrictModeFlag strict_mode = StoreIC::GetStrictMode(extra_state);
+ StrictMode strict_mode = StoreIC::GetStrictMode(extra_state);
StoreIC::GenerateRuntimeSetProperty(masm(), strict_mode);
Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
PROFILE(isolate(),
diff --git a/src/stub-cache.h b/src/stub-cache.h
index ad2b550..5d309b1 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -103,7 +103,7 @@
Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
- StrictModeFlag strict_mode,
+ StrictMode strict_mode,
KeyedAccessStoreMode store_mode);
// ---
@@ -122,7 +122,7 @@
Handle<Code> ComputeLoadElementPolymorphic(MapHandleList* receiver_maps);
Handle<Code> ComputeStoreElementPolymorphic(MapHandleList* receiver_maps,
KeyedAccessStoreMode store_mode,
- StrictModeFlag strict_mode);
+ StrictMode strict_mode);
Handle<Code> ComputePolymorphicIC(Code::Kind kind,
TypeHandleList* types,
diff --git a/src/token.h b/src/token.h
index 39bcc24..8efaa47 100644
--- a/src/token.h
+++ b/src/token.h
@@ -73,7 +73,7 @@
T(INIT_VAR, "=init_var", 2) /* AST-use only. */ \
T(INIT_LET, "=init_let", 2) /* AST-use only. */ \
T(INIT_CONST, "=init_const", 2) /* AST-use only. */ \
- T(INIT_CONST_HARMONY, "=init_const_harmony", 2) /* AST-use only. */ \
+ T(INIT_CONST_LEGACY, "=init_const_legacy", 2) /* AST-use only. */ \
T(ASSIGN, "=", 2) \
T(ASSIGN_BIT_OR, "|=", 2) \
T(ASSIGN_BIT_XOR, "^=", 2) \
diff --git a/src/types.cc b/src/types.cc
index 3840e6f..cf41bb5 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -141,9 +141,11 @@
}
return bitset;
} else if (this->IsClass()) {
- return LubBitset(*this->AsClass());
+ int bitset = Config::lub_bitset(this);
+ return bitset ? bitset : LubBitset(*this->AsClass());
} else {
- return LubBitset(*this->AsConstant());
+ int bitset = Config::lub_bitset(this);
+ return bitset ? bitset : LubBitset(*this->AsConstant());
}
}
@@ -548,9 +550,9 @@
if (type->IsBitset()) {
return Config::from_bitset(type->AsBitset(), region);
} else if (type->IsClass()) {
- return Config::from_class(type->AsClass(), region);
+ return Config::from_class(type->AsClass(), type->LubBitset(), region);
} else if (type->IsConstant()) {
- return Config::from_constant(type->AsConstant(), region);
+ return Config::from_constant(type->AsConstant(), type->LubBitset(), region);
} else {
ASSERT(type->IsUnion());
typename OtherType::UnionedHandle unioned = type->AsUnion();
diff --git a/src/types.h b/src/types.h
index 48b3933..20371a9 100644
--- a/src/types.h
+++ b/src/types.h
@@ -87,12 +87,17 @@
// Consequently, do not use pointer equality for type tests, always use Is!
//
// Internally, all 'primitive' types, and their unions, are represented as
-// bitsets via smis. Class is a heap pointer to the respective map. Only
-// Constant's, or unions containing Class'es or Constant's, require allocation.
+// bitsets. Class is a heap pointer to the respective map. Only Constant's, or
+// unions containing Class'es or Constant's, currently require allocation.
// Note that the bitset representation is closed under both Union and Intersect.
//
-// The type representation is heap-allocated, so cannot (currently) be used in
-// a concurrent compilation context.
+// There are two type representations, using different allocation:
+//
+// - class Type (zone-allocated, for compiler and concurrent compilation)
+// - class HeapType (heap-allocated, for persistent types)
+//
+// Both provide the same API, and the Convert method can be used to interconvert
+// them. For zone types, no query method touches the heap, only constructors do.
#define BITSET_TYPE_LIST(V) \
@@ -147,14 +152,15 @@
// static Handle<Unioned>::type as_union(Type*);
// static Type* from_bitset(int bitset);
// static Handle<Type>::type from_bitset(int bitset, Region*);
-// static Handle<Type>::type from_class(i::Handle<i::Map>, Region*)
-// static Handle<Type>::type from_constant(i::Handle<i::Object>, Region*);
+// static Handle<Type>::type from_class(i::Handle<Map>, int lub, Region*);
+// static Handle<Type>::type from_constant(i::Handle<Object>, int, Region*);
// static Handle<Type>::type from_union(Handle<Unioned>::type);
// static Handle<Unioned>::type union_create(int size, Region*);
// static void union_shrink(Handle<Unioned>::type, int size);
// static Handle<Type>::type union_get(Handle<Unioned>::type, int);
// static void union_set(Handle<Unioned>::type, int, Handle<Type>::type);
// static int union_length(Handle<Unioned>::type);
+// static int lub_bitset(Type*);
// }
template<class Config>
class TypeImpl : public Config::Base {
@@ -171,10 +177,10 @@
#undef DEFINE_TYPE_CONSTRUCTOR
static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
- return Config::from_class(map, region);
+ return Config::from_class(map, LubBitset(*map), region);
}
static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
- return Config::from_constant(value, region);
+ return Config::from_constant(value, LubBitset(*value), region);
}
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
@@ -335,7 +341,7 @@
}
template<class T>
static void tagged_set(Tagged* tagged, int i, T value) {
- tagged->at(i + 1) = reinterpret_cast<T>(value);
+ tagged->at(i + 1) = reinterpret_cast<void*>(value);
}
static int tagged_length(Tagged* tagged) {
return tagged->length() - 1;
@@ -375,11 +381,11 @@
}
static i::Handle<i::Map> as_class(Type* type) {
ASSERT(is_class(type));
- return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 0));
+ return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 1));
}
static i::Handle<i::Object> as_constant(Type* type) {
ASSERT(is_constant(type));
- return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 0));
+ return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 1));
}
static Unioned* as_union(Type* type) {
ASSERT(is_union(type));
@@ -399,14 +405,16 @@
static Type* from_tagged(Tagged* tagged) {
return reinterpret_cast<Type*>(tagged);
}
- static Type* from_class(i::Handle<i::Map> map, Zone* zone) {
- Tagged* tagged = tagged_create(kClassTag, 1, zone);
- tagged_set(tagged, 0, map.location());
+ static Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone) {
+ Tagged* tagged = tagged_create(kClassTag, 2, zone);
+ tagged_set(tagged, 0, lub);
+ tagged_set(tagged, 1, map.location());
return from_tagged(tagged);
}
- static Type* from_constant(i::Handle<i::Object> value, Zone* zone) {
- Tagged* tagged = tagged_create(kConstantTag, 1, zone);
- tagged_set(tagged, 0, value.location());
+ static Type* from_constant(i::Handle<i::Object> value, int lub, Zone* zone) {
+ Tagged* tagged = tagged_create(kConstantTag, 2, zone);
+ tagged_set(tagged, 0, lub);
+ tagged_set(tagged, 1, value.location());
return from_tagged(tagged);
}
static Type* from_union(Unioned* unioned) {
@@ -434,6 +442,10 @@
static int union_length(Unioned* unioned) {
return tagged_length(tagged_from_union(unioned));
}
+ static int lub_bitset(Type* type) {
+ ASSERT(is_class(type) || is_constant(type));
+ return static_cast<int>(tagged_get<intptr_t>(as_tagged(type), 0));
+ }
};
@@ -475,11 +487,12 @@
static i::Handle<Type> from_bitset(int bitset, Isolate* isolate) {
return i::handle(from_bitset(bitset), isolate);
}
- static i::Handle<Type> from_class(i::Handle<i::Map> map, Isolate* isolate) {
+ static i::Handle<Type> from_class(
+ i::Handle<i::Map> map, int lub, Isolate* isolate) {
return i::Handle<Type>::cast(i::Handle<Object>::cast(map));
}
static i::Handle<Type> from_constant(
- i::Handle<i::Object> value, Isolate* isolate) {
+ i::Handle<i::Object> value, int lub, Isolate* isolate) {
i::Handle<Box> box = isolate->factory()->NewBox(value);
return i::Handle<Type>::cast(i::Handle<Object>::cast(box));
}
@@ -506,6 +519,9 @@
static int union_length(i::Handle<Unioned> unioned) {
return unioned->length();
}
+ static int lub_bitset(Type* type) {
+ return 0; // kNone, which causes recomputation.
+ }
};
typedef TypeImpl<ZoneTypeConfig> Type;
diff --git a/src/v8globals.h b/src/v8globals.h
index 7d8d1b7..2e0ead3 100644
--- a/src/v8globals.h
+++ b/src/v8globals.h
@@ -465,11 +465,11 @@
// User declared variables:
VAR, // declared via 'var', and 'function' declarations
- CONST, // declared via 'const' declarations
+ CONST_LEGACY, // declared via legacy 'const' declarations
LET, // declared via 'let' declarations (first lexical)
- CONST_HARMONY, // declared via 'const' declarations in harmony mode
+ CONST, // declared via 'const' declarations
MODULE, // declared via 'module' declaration (last lexical)
@@ -510,7 +510,7 @@
inline bool IsImmutableVariableMode(VariableMode mode) {
- return mode == CONST || (mode >= CONST_HARMONY && mode <= MODULE);
+ return (mode >= CONST && mode <= MODULE) || mode == CONST_LEGACY;
}
diff --git a/src/v8natives.js b/src/v8natives.js
index c850a4b..f183afb 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -1282,7 +1282,7 @@
throw MakeTypeError("called_on_non_object", ["Object.freeze"]);
}
var isProxy = %IsJSProxy(obj);
- if (isProxy || %HasNonStrictArgumentsElements(obj) || %IsObserved(obj)) {
+ if (isProxy || %HasSloppyArgumentsElements(obj) || %IsObserved(obj)) {
if (isProxy) {
ProxyFix(obj);
}
diff --git a/src/variables.cc b/src/variables.cc
index 488da42..6c4ea52 100644
--- a/src/variables.cc
+++ b/src/variables.cc
@@ -40,9 +40,9 @@
const char* Variable::Mode2String(VariableMode mode) {
switch (mode) {
case VAR: return "VAR";
- case CONST: return "CONST";
+ case CONST_LEGACY: return "CONST_LEGACY";
case LET: return "LET";
- case CONST_HARMONY: return "CONST_HARMONY";
+ case CONST: return "CONST";
case MODULE: return "MODULE";
case DYNAMIC: return "DYNAMIC";
case DYNAMIC_GLOBAL: return "DYNAMIC_GLOBAL";
diff --git a/src/variables.h b/src/variables.h
index 39451d5..401d044 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -168,7 +168,7 @@
// If this field is set, this variable references the stored locally bound
// variable, but it might be shadowed by variable bindings introduced by
- // non-strict 'eval' calls between the reference scope (inclusive) and the
+ // sloppy 'eval' calls between the reference scope (inclusive) and the
// binding scope (exclusive).
Variable* local_if_not_shadowed_;
diff --git a/src/version.cc b/src/version.cc
index 4319e1a..3c6f053 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 25
-#define BUILD_NUMBER 7
-#define PATCH_LEVEL 2
+#define BUILD_NUMBER 8
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/src/win32-headers.h b/src/win32-headers.h
index 98b0120..ba595b9 100644
--- a/src/win32-headers.h
+++ b/src/win32-headers.h
@@ -94,6 +94,7 @@
#undef NONE
#undef ANY
#undef IGNORE
+#undef STRICT
#undef GetObject
#undef CreateSemaphore
#undef Yield
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 5345e9e..d4f5e03 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -799,7 +799,7 @@
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
__ j(not_zero, &shift_arguments);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ movp(rbx, args.GetArgumentOperand(1));
__ JumpIfSmi(rbx, &convert_to_object, Label::kNear);
@@ -990,7 +990,7 @@
Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte));
__ j(not_equal, &push_receiver);
- // Compute the receiver in non-strict mode.
+ // Compute the receiver in sloppy mode.
__ JumpIfSmi(rbx, &call_to_object, Label::kNear);
__ CompareRoot(rbx, Heap::kNullValueRootIndex);
__ j(equal, &use_global_receiver);
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index d6b0dd0..84706fe 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -1062,7 +1062,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) {
// Stack layout:
// rsp[0] : return address
// rsp[8] : number of parameters (tagged)
@@ -1123,7 +1123,7 @@
__ lea(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize));
// 3. Arguments object.
- __ addq(r8, Immediate(Heap::kArgumentsObjectSize));
+ __ addq(r8, Immediate(Heap::kSloppyArgumentsObjectSize));
// Do the allocation of all three objects in one go.
__ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT);
@@ -1137,7 +1137,7 @@
__ testq(rbx, rbx);
__ j(not_zero, &has_mapped_parameters, Label::kNear);
- const int kIndex = Context::ARGUMENTS_BOILERPLATE_INDEX;
+ const int kIndex = Context::SLOPPY_ARGUMENTS_BOILERPLATE_INDEX;
__ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex)));
__ jmp(©, Label::kNear);
@@ -1174,7 +1174,7 @@
// Set up the elements pointer in the allocated arguments object.
// If we allocated a parameter map, edi will point there, otherwise to the
// backing store.
- __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSize));
+ __ lea(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize));
__ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
// rax = address of new object (tagged)
@@ -1187,7 +1187,7 @@
__ testq(rbx, rbx);
__ j(zero, &skip_parameter_map);
- __ LoadRoot(kScratchRegister, Heap::kNonStrictArgumentsElementsMapRootIndex);
+ __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex);
// rbx contains the untagged argument count. Add 2 and tag to write.
__ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
__ Integer64PlusConstantToSmi(r9, rbx, 2);
@@ -1280,7 +1280,7 @@
}
-void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) {
+void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) {
// rsp[0] : return address
// rsp[8] : number of parameters
// rsp[16] : receiver displacement
@@ -1343,7 +1343,7 @@
__ j(zero, &add_arguments_object, Label::kNear);
__ lea(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize));
__ bind(&add_arguments_object);
- __ addq(rcx, Immediate(Heap::kArgumentsObjectSizeStrict));
+ __ addq(rcx, Immediate(Heap::kStrictArgumentsObjectSize));
// Do the allocation of both objects in one go.
__ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT);
@@ -1352,7 +1352,7 @@
__ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
__ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset));
const int offset =
- Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX);
+ Context::SlotOffset(Context::STRICT_ARGUMENTS_BOILERPLATE_INDEX);
__ movp(rdi, Operand(rdi, offset));
// Copy the JS object part.
@@ -1378,7 +1378,7 @@
// Set up the elements pointer in the allocated arguments object and
// initialize the header in the elements fixed array.
- __ lea(rdi, Operand(rax, Heap::kArgumentsObjectSizeStrict));
+ __ lea(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize));
__ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi);
__ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex);
__ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister);
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index ea50191..67d94f9 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -133,10 +133,10 @@
}
#endif
- // Classic mode functions and builtins need to replace the receiver with the
+ // Sloppy mode functions and builtins need to replace the receiver with the
// global proxy when called as functions (without an explicit receiver
// object).
- if (info->is_classic_mode() && !info->is_native()) {
+ if (info->strict_mode() == SLOPPY && !info->is_native()) {
Label ok;
// +1 for return address.
StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
@@ -242,12 +242,12 @@
// The stub will rewrite receiver and parameter count if the previous
// stack frame was an arguments adapter frame.
ArgumentsAccessStub::Type type;
- if (!is_classic_mode()) {
+ if (strict_mode() == STRICT) {
type = ArgumentsAccessStub::NEW_STRICT;
} else if (function()->has_duplicate_parameters()) {
- type = ArgumentsAccessStub::NEW_NON_STRICT_SLOW;
+ type = ArgumentsAccessStub::NEW_SLOPPY_SLOW;
} else {
- type = ArgumentsAccessStub::NEW_NON_STRICT_FAST;
+ type = ArgumentsAccessStub::NEW_SLOPPY_FAST;
}
ArgumentsAccessStub stub(type);
__ CallStub(&stub);
@@ -273,7 +273,7 @@
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableDeclaration* function = scope()->function();
ASSERT(function->proxy()->var()->mode() == CONST ||
- function->proxy()->var()->mode() == CONST_HARMONY);
+ function->proxy()->var()->mode() == CONST_LEGACY);
ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
@@ -756,7 +756,7 @@
VariableProxy* proxy = declaration->proxy();
VariableMode mode = declaration->mode();
Variable* variable = proxy->var();
- bool hole_init = mode == CONST || mode == CONST_HARMONY || mode == LET;
+ bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
switch (variable->location()) {
case Variable::UNALLOCATED:
globals_->Add(variable->name(), zone());
@@ -1285,7 +1285,7 @@
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(info->language_mode(), info->is_generator());
+ FastNewClosureStub stub(info->strict_mode(), info->is_generator());
__ Move(rbx, info);
__ CallStub(&stub);
} else {
@@ -1315,7 +1315,7 @@
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
Immediate(0));
@@ -1329,7 +1329,7 @@
// If no outer scope calls eval, we do not need to check more
// context extensions. If we have reached an eval scope, we check
// all extensions from this point.
- if (!s->outer_scope_calls_non_strict_eval() || s->is_eval_scope()) break;
+ if (!s->outer_scope_calls_sloppy_eval() || s->is_eval_scope()) break;
s = s->outer_scope();
}
@@ -1374,7 +1374,7 @@
for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
if (s->num_heap_slots() > 0) {
- if (s->calls_non_strict_eval()) {
+ if (s->calls_sloppy_eval()) {
// Check that extension is NULL.
__ cmpq(ContextOperand(context, Context::EXTENSION_INDEX),
Immediate(0));
@@ -1411,14 +1411,13 @@
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ movp(rax, ContextSlotOperandCheckExtensions(local, slow));
- if (local->mode() == LET ||
- local->mode() == CONST ||
- local->mode() == CONST_HARMONY) {
+ if (local->mode() == LET || local->mode() == CONST ||
+ local->mode() == CONST_LEGACY) {
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, done);
- if (local->mode() == CONST) {
+ if (local->mode() == CONST_LEGACY) {
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
- } else { // LET || CONST_HARMONY
+ } else { // LET || CONST
__ Push(var->name());
__ CallRuntime(Runtime::kThrowReferenceError, 1);
}
@@ -1483,7 +1482,7 @@
// Check that we always have valid source position.
ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
ASSERT(proxy->position() != RelocInfo::kNoPosition);
- skip_init_check = var->mode() != CONST &&
+ skip_init_check = var->mode() != CONST_LEGACY &&
var->initializer_position() < proxy->position();
}
@@ -1493,14 +1492,14 @@
GetVar(rax, var);
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &done, Label::kNear);
- if (var->mode() == LET || var->mode() == CONST_HARMONY) {
+ if (var->mode() == LET || var->mode() == CONST) {
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ Push(var->name());
__ CallRuntime(Runtime::kThrowReferenceError, 1);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
- ASSERT(var->mode() == CONST);
+ ASSERT(var->mode() == CONST_LEGACY);
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
}
__ bind(&done);
@@ -2381,7 +2380,7 @@
__ movp(rcx, rax);
__ pop(rdx);
__ pop(rax); // Restore value.
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic);
@@ -2404,11 +2403,11 @@
void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, LanguageMode mode) {
+ Handle<String> name, StrictMode strict_mode) {
__ push(rax); // Value.
__ push(rsi); // Context.
__ Push(name);
- __ Push(Smi::FromInt(mode));
+ __ Push(Smi::FromInt(strict_mode));
__ CallRuntime(Runtime::kStoreContextSlot, 4);
}
@@ -2421,7 +2420,7 @@
__ movp(rdx, GlobalObjectOperand());
CallStoreIC();
- } else if (op == Token::INIT_CONST) {
+ } else if (op == Token::INIT_CONST_LEGACY) {
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
@@ -2443,7 +2442,7 @@
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
@@ -2457,11 +2456,11 @@
EmitStoreToStackLocalOrContextSlot(var, location);
}
- } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
+ } else if (!var->is_const_mode() || op == Token::INIT_CONST) {
// Assignment to var or initializing assignment to let/const
// in harmony mode.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ EmitCallStoreContextSlot(var->name(), strict_mode());
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
MemOperand location = VarOperand(var, rcx);
@@ -2502,7 +2501,7 @@
__ pop(rdx);
// Record source code position before IC call.
SetSourcePosition(expr->position());
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->AssignmentFeedbackId());
@@ -2552,7 +2551,7 @@
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
- // is a classic mode method.
+ // is a sloppy mode method.
__ Push(isolate()->factory()->undefined_value());
flags = NO_CALL_FUNCTION_FLAGS;
} else {
@@ -2670,7 +2669,7 @@
__ push(args.GetReceiverOperand());
// Push the language mode.
- __ Push(Smi::FromInt(language_mode()));
+ __ Push(Smi::FromInt(strict_mode()));
// Push the start position of the scope the calls resides in.
__ Push(Smi::FromInt(scope()->start_position()));
@@ -4166,20 +4165,18 @@
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
- ? kNonStrictMode : kStrictMode;
- __ Push(Smi::FromInt(strict_mode_flag));
+ __ Push(Smi::FromInt(strict_mode()));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(rax);
} else if (proxy != NULL) {
Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
// but "delete this" is allowed.
- ASSERT(language_mode() == CLASSIC_MODE || var->is_this());
+ ASSERT(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
__ push(GlobalObjectOperand());
__ Push(var->name());
- __ Push(Smi::FromInt(kNonStrictMode));
+ __ Push(Smi::FromInt(SLOPPY));
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(rax);
} else if (var->IsStackAllocated() || var->IsContextSlot()) {
@@ -4441,7 +4438,7 @@
case KEYED_PROPERTY: {
__ pop(rcx);
__ pop(rdx);
- Handle<Code> ic = is_classic_mode()
+ Handle<Code> ic = strict_mode() == SLOPPY
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
CallIC(ic, expr->CountStoreFeedbackId());
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index d2340c8..40fdc60 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -734,7 +734,7 @@
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
@@ -852,7 +852,7 @@
// Load the elements into scratch1 and check its map. If not, jump
// to the unmapped lookup with the parameter map in scratch1.
- Handle<Map> arguments_map(heap->non_strict_arguments_elements_map());
+ Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
__ movp(scratch1, FieldOperand(object, JSObject::kElementsOffset));
__ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
@@ -909,7 +909,7 @@
}
-void KeyedLoadIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
@@ -934,7 +934,7 @@
}
-void KeyedStoreIC::GenerateNonStrictArguments(MacroAssembler* masm) {
+void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
@@ -1151,7 +1151,7 @@
void StoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
@@ -1172,7 +1172,7 @@
void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
- StrictModeFlag strict_mode) {
+ StrictMode strict_mode) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 1b6a97b..e05be03 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -154,10 +154,10 @@
}
#endif
- // Classic mode functions need to replace the receiver with the global proxy
+ // Sloppy mode functions need to replace the receiver with the global proxy
// when called as functions (without an explicit receiver object).
if (info_->this_has_uses() &&
- info_->is_classic_mode() &&
+ info_->strict_mode() == SLOPPY &&
!info_->is_native()) {
Label ok;
StackArgumentsAccessor args(rsp, scope()->num_parameters());
@@ -273,6 +273,13 @@
}
+void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
+ if (!instr->IsLazyBailout() && !instr->IsGap()) {
+ safepoints_.BumpLastLazySafepointIndex();
+ }
+}
+
+
bool LCodeGen::GenerateJumpTable() {
Label needs_frame;
if (jump_table_.length() > 0) {
@@ -1036,8 +1043,7 @@
// Check for negative zero.
HMod* hmod = instr->hydrogen();
- if (hmod->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hmod->left()->CanBeNegative()) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label remainder_not_zero;
__ j(not_zero, &remainder_not_zero, Label::kNear);
__ cmpl(dividend, Immediate(0));
@@ -1048,12 +1054,7 @@
void LCodeGen::DoModI(LModI* instr) {
- if (instr->hydrogen()->RightIsPowerOf2()) {
- return DoModByPowerOf2I(reinterpret_cast<LModByPowerOf2I*>(instr));
- }
HMod* hmod = instr->hydrogen();
- HValue* left = hmod->left();
- HValue* right = hmod->right();
Register left_reg = ToRegister(instr->left());
ASSERT(left_reg.is(rax));
@@ -1066,14 +1067,14 @@
Label done;
// Check for x % 0, idiv would signal a divide error. We have to
// deopt in this case because we can't return a NaN.
- if (right->CanBeZero()) {
+ if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(right_reg, right_reg);
DeoptimizeIf(zero, instr->environment());
}
// Check for kMinInt % -1, idiv would signal a divide error. We
// have to deopt if we care about -0, because we can't return that.
- if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) {
+ if (hmod->CheckFlag(HValue::kCanOverflow)) {
Label no_overflow_possible;
__ cmpl(left_reg, Immediate(kMinInt));
__ j(not_zero, &no_overflow_possible, Label::kNear);
@@ -1093,9 +1094,7 @@
__ cdq();
// If we care about -0, test if the dividend is <0 and the result is 0.
- if (left->CanBeNegative() &&
- hmod->CanBeZero() &&
- hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
Label positive_left;
__ testl(left_reg, left_reg);
__ j(not_sign, &positive_left, Label::kNear);
@@ -1159,8 +1158,7 @@
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ testl(dividend, dividend);
DeoptimizeIf(zero, instr->environment());
}
@@ -1178,14 +1176,12 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ testl(dividend, dividend);
DeoptimizeIf(zero, instr->environment());
}
// Check for (kMinInt / -1).
- if (hdiv->CheckFlag(HValue::kCanOverflow) &&
- hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1) {
+ if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
__ cmpl(dividend, Immediate(kMinInt));
DeoptimizeIf(zero, instr->environment());
}
@@ -1221,8 +1217,7 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
- if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) &&
- hdiv->left()->RangeCanInclude(0) && divisor < 0) {
+ if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
__ testl(dividend, dividend);
DeoptimizeIf(zero, instr->environment());
}
@@ -1243,6 +1238,7 @@
void LCodeGen::DoDivI(LDivI* instr) {
+ HBinaryOperation* hdiv = instr->hydrogen();
Register dividend = ToRegister(instr->left());
Register divisor = ToRegister(instr->right());
Register remainder = ToRegister(instr->temp());
@@ -1254,7 +1250,6 @@
ASSERT(!divisor.is(rdx));
// Check for x / 0.
- HBinaryOperation* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(divisor, divisor);
DeoptimizeIf(zero, instr->environment());
@@ -1284,7 +1279,7 @@
__ cdq();
__ idivl(divisor);
- if (instr->is_flooring()) {
+ if (hdiv->IsMathFloorOfDiv()) {
Label done;
__ testl(remainder, remainder);
__ j(zero, &done, Label::kNear);
@@ -1292,8 +1287,7 @@
__ sarl(remainder, Immediate(31));
__ addl(result, remainder);
__ bind(&done);
- } else if (!instr->hydrogen()->CheckFlag(
- HInstruction::kAllUsesTruncatingToInt32)) {
+ } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
// Deoptimize if remainder is not 0.
__ testl(remainder, remainder);
DeoptimizeIf(not_zero, instr->environment());
@@ -1913,7 +1907,6 @@
BinaryOpICStub stub(instr->op(), NO_OVERWRITE);
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
- __ nop(); // Signals no inlined code.
}
@@ -3001,7 +2994,7 @@
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4062,8 +4055,7 @@
ASSERT(ToRegister(instr->value()).is(rax));
__ Move(rcx, instr->hydrogen()->name());
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag());
+ Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
@@ -4198,7 +4190,7 @@
case FAST_HOLEY_SMI_ELEMENTS:
case FAST_HOLEY_DOUBLE_ELEMENTS:
case DICTIONARY_ELEMENTS:
- case NON_STRICT_ARGUMENTS_ELEMENTS:
+ case SLOPPY_ARGUMENTS_ELEMENTS:
UNREACHABLE();
break;
}
@@ -4349,7 +4341,7 @@
ASSERT(ToRegister(instr->key()).is(rcx));
ASSERT(ToRegister(instr->value()).is(rax));
- Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode)
+ Handle<Code> ic = instr->strict_mode() == STRICT
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
: isolate()->builtins()->KeyedStoreIC_Initialize();
CallCode(ic, RelocInfo::CODE_TARGET, instr);
@@ -5301,7 +5293,7 @@
// space for nested functions that don't need literals cloning.
bool pretenure = instr->hydrogen()->pretenure();
if (!pretenure && instr->hydrogen()->has_no_literals()) {
- FastNewClosureStub stub(instr->hydrogen()->language_mode(),
+ FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
instr->hydrogen()->is_generator());
__ Move(rbx, instr->hydrogen()->shared_info());
CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
diff --git a/src/x64/lithium-codegen-x64.h b/src/x64/lithium-codegen-x64.h
index 0f1a9cd..e2c5a0a 100644
--- a/src/x64/lithium-codegen-x64.h
+++ b/src/x64/lithium-codegen-x64.h
@@ -130,9 +130,7 @@
#undef DECLARE_DO
private:
- StrictModeFlag strict_mode_flag() const {
- return info()->is_classic_mode() ? kNonStrictMode : kStrictMode;
- }
+ StrictMode strict_mode() const { return info()->strict_mode(); }
LPlatformChunk* chunk() const { return chunk_; }
Scope* scope() const { return scope_; }
@@ -159,6 +157,7 @@
// Code generation passes. Returns true if code generation should
// continue.
+ void GenerateBodyInstructionPre(LInstruction* instr) V8_OVERRIDE;
bool GeneratePrologue();
bool GenerateDeferredCode();
bool GenerateJumpTable();
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 74390e6..beb0f2b 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -630,15 +630,6 @@
instr->MarkAsCall();
instr = AssignPointerMap(instr);
- if (hinstr->HasObservableSideEffects()) {
- ASSERT(hinstr->next()->IsSimulate());
- HSimulate* sim = HSimulate::cast(hinstr->next());
- ASSERT(instruction_pending_deoptimization_environment_ == NULL);
- ASSERT(pending_deoptimization_ast_id_.IsNone());
- instruction_pending_deoptimization_environment_ = instr;
- pending_deoptimization_ast_id_ = sim->ast_id();
- }
-
// If instruction does not have side-effects lazy deoptimization
// after the call will try to deoptimize to the point before the call.
// Thus we still need to attach environment to this call even if
@@ -916,6 +907,26 @@
instr = AssignEnvironment(instr);
}
chunk_->AddInstruction(instr, current_block_);
+
+ if (instr->IsCall()) {
+ HValue* hydrogen_value_for_lazy_bailout = current;
+ LInstruction* instruction_needing_environment = NULL;
+ if (current->HasObservableSideEffects()) {
+ HSimulate* sim = HSimulate::cast(current->next());
+ instruction_needing_environment = instr;
+ sim->ReplayEnvironment(current_block_->last_environment());
+ hydrogen_value_for_lazy_bailout = sim;
+ }
+ LInstruction* bailout = AssignEnvironment(new(zone()) LLazyBailout());
+ bailout->set_hydrogen_value(hydrogen_value_for_lazy_bailout);
+ chunk_->AddInstruction(bailout, current_block_);
+ if (instruction_needing_environment != NULL) {
+ // Store the lazy deopt environment with the instruction if needed.
+ // Right now it is only used for LInstanceOfKnownGlobal.
+ instruction_needing_environment->
+ SetDeferredLazyDeoptimizationEnvironment(bailout->environment());
+ }
+ }
}
current_instruction_ = old_current;
}
@@ -1248,16 +1259,15 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LDivByPowerOf2I(dividend, divisor));
- bool can_deopt =
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- (instr->CheckFlag(HValue::kCanOverflow) &&
- instr->left()->RangeCanInclude(kMinInt) && divisor == -1) ||
+ LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I(
+ dividend, divisor));
+ if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) ||
(!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
- divisor != 1 && divisor != -1);
- return can_deopt ? AssignEnvironment(result) : result;
+ divisor != 1 && divisor != -1)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1269,15 +1279,14 @@
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp1 = FixedTemp(rax);
LOperand* temp2 = FixedTemp(rdx);
- LInstruction* result =
- DefineFixed(
- new(zone()) LDivByConstI(dividend, divisor, temp1, temp2), rdx);
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0) ||
- !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32);
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineFixed(new(zone()) LDivByConstI(
+ dividend, divisor, temp1, temp2), rdx);
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) ||
+ !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1288,9 +1297,16 @@
LOperand* dividend = UseFixed(instr->left(), rax);
LOperand* divisor = UseRegister(instr->right());
LOperand* temp = FixedTemp(rdx);
- LInstruction* result =
- DefineFixed(new(zone()) LDivI(dividend, divisor, temp), rax);
- return AssignEnvironment(result);
+ LInstruction* result = DefineFixed(new(zone()) LDivI(
+ dividend, divisor, temp), rax);
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
+ instr->CheckFlag(HValue::kCanOverflow) ||
+ (!instr->IsMathFloorOfDiv() &&
+ !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1339,8 +1355,7 @@
rdx);
bool can_deopt =
divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(0) && divisor < 0);
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
return can_deopt ? AssignEnvironment(result) : result;
}
@@ -1362,12 +1377,12 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegisterAtStart(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineSameAsFirst(new(zone()) LModByPowerOf2I(dividend, divisor));
- bool can_deopt =
- instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative();
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I(
+ dividend, divisor));
+ if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1379,14 +1394,12 @@
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp1 = FixedTemp(rax);
LOperand* temp2 = FixedTemp(rdx);
- LInstruction* result =
- DefineFixed(
- new(zone()) LModByConstI(dividend, divisor, temp1, temp2), rax);
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative());
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineFixed(new(zone()) LModByConstI(
+ dividend, divisor, temp1, temp2), rax);
+ if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1397,16 +1410,13 @@
LOperand* dividend = UseFixed(instr->left(), rax);
LOperand* divisor = UseRegister(instr->right());
LOperand* temp = FixedTemp(rdx);
- LInstruction* result =
- DefineFixed(new(zone()) LModI(dividend, divisor, temp), rdx);
- bool can_deopt = (instr->right()->CanBeZero() ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->RangeCanInclude(kMinInt) &&
- instr->right()->RangeCanInclude(-1)) ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) &&
- instr->left()->CanBeNegative() &&
- instr->CanBeZero()));
- return can_deopt ? AssignEnvironment(result) : result;
+ LInstruction* result = DefineFixed(new(zone()) LModI(
+ dividend, divisor, temp), rdx);
+ if (instr->CheckFlag(HValue::kCanBeDivByZero) ||
+ instr->CheckFlag(HValue::kBailoutOnMinusZero)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -2436,21 +2446,6 @@
LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) {
instr->ReplayEnvironment(current_block_->last_environment());
-
- // If there is an instruction pending deoptimization environment create a
- // lazy bailout instruction to capture the environment.
- if (pending_deoptimization_ast_id_ == instr->ast_id()) {
- LLazyBailout* lazy_bailout = new(zone()) LLazyBailout;
- LInstruction* result = AssignEnvironment(lazy_bailout);
- // Store the lazy deopt environment with the instruction if needed. Right
- // now it is only used for LInstanceOfKnownGlobal.
- instruction_pending_deoptimization_environment_->
- SetDeferredLazyDeoptimizationEnvironment(result->environment());
- instruction_pending_deoptimization_environment_ = NULL;
- pending_deoptimization_ast_id_ = BailoutId::None();
- return result;
- }
-
return NULL;
}
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 4df350d..e03604d 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -737,8 +737,6 @@
LOperand* right() { return inputs_[1]; }
LOperand* temp() { return temps_[0]; }
- bool is_flooring() { return hydrogen_value()->IsMathFloorOfDiv(); }
-
DECLARE_CONCRETE_INSTRUCTION(DivI, "div-i")
DECLARE_HYDROGEN_ACCESSOR(BinaryOperation)
};
@@ -2172,7 +2170,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2227,7 +2225,7 @@
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
+ StrictMode strict_mode() { return hydrogen()->strict_mode(); }
};
@@ -2668,9 +2666,7 @@
current_instruction_(NULL),
current_block_(NULL),
next_block_(NULL),
- allocator_(allocator),
- instruction_pending_deoptimization_environment_(NULL),
- pending_deoptimization_ast_id_(BailoutId::None()) { }
+ allocator_(allocator) { }
// Build the sequence for the graph.
LPlatformChunk* Build();
@@ -2815,8 +2811,6 @@
HBasicBlock* current_block_;
HBasicBlock* next_block_;
LAllocator* allocator_;
- LInstruction* instruction_pending_deoptimization_environment_;
- BailoutId pending_deoptimization_ast_id_;
DISALLOW_COPY_AND_ASSIGN(LChunkBuilder);
};