Version 3.25.22 (based on bleeding_edge revision r20129)
Increase the "local variables in a function" limit (issue 3205).
Implement ES6 symbol registry and predefined symbols.
Throw exception on invalid string length instead of OOM (Chromium issue 349329).
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@20133 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/a64/builtins-a64.cc b/src/a64/builtins-a64.cc
index 59d4dd2..ec452da 100644
--- a/src/a64/builtins-a64.cc
+++ b/src/a64/builtins-a64.cc
@@ -861,7 +861,7 @@
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(x0, x1, fp, lr);
- __ Mov(x1, Operand(ExternalReference::isolate_address(masm->isolate())));
+ __ Mov(x1, ExternalReference::isolate_address(masm->isolate()));
__ CallCFunction(
ExternalReference::get_make_code_young_function(masm->isolate()), 2);
__ Pop(lr, fp, x1, x0);
@@ -901,7 +901,7 @@
{
FrameScope scope(masm, StackFrame::MANUAL);
__ Push(x0, x1, fp, lr);
- __ Mov(x1, Operand(ExternalReference::isolate_address(masm->isolate())));
+ __ Mov(x1, ExternalReference::isolate_address(masm->isolate()));
__ CallCFunction(
ExternalReference::get_mark_code_as_executed_function(
masm->isolate()), 2);
@@ -963,7 +963,7 @@
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
- __ Mov(x0, Operand(Smi::FromInt(static_cast<int>(type))));
+ __ Mov(x0, Smi::FromInt(static_cast<int>(type)));
__ Push(x0);
__ CallRuntime(Runtime::kNotifyDeoptimized, 1);
}
@@ -1019,7 +1019,7 @@
// If the code object is null, just return to the unoptimized code.
Label skip;
- __ CompareAndBranch(x0, Operand(Smi::FromInt(0)), ne, &skip);
+ __ CompareAndBranch(x0, Smi::FromInt(0), ne, &skip);
__ Ret();
__ Bind(&skip);
@@ -1358,7 +1358,7 @@
// Use inline caching to access the arguments.
__ Ldr(current, MemOperand(fp, kIndexOffset));
- __ Add(current, current, Operand(Smi::FromInt(1)));
+ __ Add(current, current, Smi::FromInt(1));
__ Str(current, MemOperand(fp, kIndexOffset));
// Test if the copy loop has finished copying all the elements from the
@@ -1402,7 +1402,7 @@
static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
__ SmiTag(x10, x0);
- __ Mov(x11, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Mov(x11, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ Push(lr, fp);
__ Push(x11, x1, x10);
__ Add(fp, jssp,
diff --git a/src/a64/code-stubs-a64.cc b/src/a64/code-stubs-a64.cc
index 5cd3974..3fd0615 100644
--- a/src/a64/code-stubs-a64.cc
+++ b/src/a64/code-stubs-a64.cc
@@ -1080,7 +1080,7 @@
ASSERT((cond == gt) || (cond == ge)); // remaining cases
ncr = LESS;
}
- __ Mov(x10, Operand(Smi::FromInt(ncr)));
+ __ Mov(x10, Smi::FromInt(ncr));
__ Push(x10);
}
@@ -1111,7 +1111,7 @@
}
AllowExternalCallThatCantCauseGC scope(masm);
- __ Mov(x0, Operand(ExternalReference::isolate_address(masm->isolate())));
+ __ Mov(x0, ExternalReference::isolate_address(masm->isolate()));
__ CallCFunction(
ExternalReference::store_buffer_overflow_function(masm->isolate()),
1, 0);
@@ -1490,7 +1490,7 @@
if (do_gc) {
// Call Runtime::PerformGC, passing x0 (the result parameter for
// PerformGC) and x1 (the isolate).
- __ Mov(x1, Operand(ExternalReference::isolate_address(masm->isolate())));
+ __ Mov(x1, ExternalReference::isolate_address(masm->isolate()));
__ CallCFunction(
ExternalReference::perform_gc_function(isolate), 2, 0);
}
@@ -1507,7 +1507,7 @@
// Prepare AAPCS64 arguments to pass to the builtin.
__ Mov(x0, argc);
__ Mov(x1, argv);
- __ Mov(x2, Operand(ExternalReference::isolate_address(isolate)));
+ __ Mov(x2, ExternalReference::isolate_address(isolate));
// Store the return address on the stack, in the space previously allocated
// by EnterExitFrame. The return address is queried by
@@ -1820,8 +1820,8 @@
int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
int64_t bad_frame_pointer = -1L; // Bad frame pointer to fail if it is used.
__ Mov(x13, bad_frame_pointer);
- __ Mov(x12, Operand(Smi::FromInt(marker)));
- __ Mov(x11, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
+ __ Mov(x12, Smi::FromInt(marker));
+ __ Mov(x11, ExternalReference(Isolate::kCEntryFPAddress, isolate));
__ Ldr(x10, MemOperand(x11));
__ Push(x13, xzr, x12, x10);
@@ -1832,11 +1832,11 @@
// outermost JS call.
Label non_outermost_js, done;
ExternalReference js_entry_sp(Isolate::kJSEntrySPAddress, isolate);
- __ Mov(x10, Operand(ExternalReference(js_entry_sp)));
+ __ Mov(x10, ExternalReference(js_entry_sp));
__ Ldr(x11, MemOperand(x10));
__ Cbnz(x11, &non_outermost_js);
__ Str(fp, MemOperand(x10));
- __ Mov(x12, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
+ __ Mov(x12, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ Push(x12);
__ B(&done);
__ Bind(&non_outermost_js);
@@ -1905,7 +1905,7 @@
ExternalReference entry(is_construct ? Builtins::kJSConstructEntryTrampoline
: Builtins::kJSEntryTrampoline,
isolate);
- __ Mov(x10, Operand(entry));
+ __ Mov(x10, entry);
// Call the JSEntryTrampoline.
__ Ldr(x11, MemOperand(x10)); // Dereference the address.
@@ -1929,15 +1929,15 @@
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ Pop(x10);
- __ Cmp(x10, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
+ __ Cmp(x10, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ B(ne, &non_outermost_js_2);
- __ Mov(x11, Operand(ExternalReference(js_entry_sp)));
+ __ Mov(x11, ExternalReference(js_entry_sp));
__ Str(xzr, MemOperand(x11));
__ Bind(&non_outermost_js_2);
// Restore the top frame descriptors from the stack.
__ Pop(x10);
- __ Mov(x11, Operand(ExternalReference(Isolate::kCEntryFPAddress, isolate)));
+ __ Mov(x11, ExternalReference(Isolate::kCEntryFPAddress, isolate));
__ Str(x10, MemOperand(x11));
// Reset the stack to the callee saved registers.
@@ -2017,8 +2017,8 @@
__ LoadTrueFalseRoots(res_true, res_false);
} else {
// This is counter-intuitive, but correct.
- __ Mov(res_true, Operand(Smi::FromInt(0)));
- __ Mov(res_false, Operand(Smi::FromInt(1)));
+ __ Mov(res_true, Smi::FromInt(0));
+ __ Mov(res_false, Smi::FromInt(1));
}
// Check that the left hand side is a JS object and load its map as a side
@@ -2188,7 +2188,7 @@
__ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ Ldr(caller_ctx, MemOperand(caller_fp,
StandardFrameConstants::kContextOffset));
- __ Cmp(caller_ctx, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ Csel(local_fp, fp, caller_fp, ne);
__ B(ne, &skip_adaptor);
@@ -2238,7 +2238,7 @@
ArgumentsAdaptorFrameConstants::kLengthOffset));
__ Poke(x11, 0 * kXRegSize);
__ Add(x10, caller_fp, Operand::UntagSmiAndScale(x11, kPointerSizeLog2));
- __ Add(x10, x10, Operand(StandardFrameConstants::kCallerSPOffset));
+ __ Add(x10, x10, StandardFrameConstants::kCallerSPOffset);
__ Poke(x10, 1 * kXRegSize);
__ Bind(&runtime);
@@ -2271,7 +2271,7 @@
__ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ Ldr(caller_ctx, MemOperand(caller_fp,
StandardFrameConstants::kContextOffset));
- __ Cmp(caller_ctx, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ B(eq, &adaptor_frame);
// No adaptor, parameter count = argument count.
@@ -2473,7 +2473,7 @@
__ Str(index, MemOperand(elements, x10));
__ Sub(x10, x10, kParameterMapHeaderSize - FixedArray::kHeaderSize);
__ Str(the_hole, MemOperand(backing_store, x10));
- __ Add(index, index, Operand(Smi::FromInt(1)));
+ __ Add(index, index, Smi::FromInt(1));
__ Bind(¶meters_test);
__ Cbnz(loop_count, ¶meters_loop);
@@ -2542,7 +2542,7 @@
__ Ldr(caller_fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ Ldr(caller_ctx, MemOperand(caller_fp,
StandardFrameConstants::kContextOffset));
- __ Cmp(caller_ctx, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(caller_ctx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ B(ne, &try_allocate);
// x1 param_count_smi number of parameters passed to function (smi)
@@ -2728,7 +2728,7 @@
ExternalReference::address_of_regexp_stack_memory_address(isolate);
ExternalReference address_of_regexp_stack_memory_size =
ExternalReference::address_of_regexp_stack_memory_size(isolate);
- __ Mov(x10, Operand(address_of_regexp_stack_memory_size));
+ __ Mov(x10, address_of_regexp_stack_memory_size);
__ Ldr(x10, MemOperand(x10));
__ Cbz(x10, &runtime);
@@ -2750,7 +2750,7 @@
// Check the type of the RegExp. Only continue if type is JSRegExp::IRREGEXP.
__ Ldr(x10, FieldMemOperand(regexp_data, JSRegExp::kDataTagOffset));
- __ Cmp(x10, Operand(Smi::FromInt(JSRegExp::IRREGEXP)));
+ __ Cmp(x10, Smi::FromInt(JSRegExp::IRREGEXP));
__ B(ne, &runtime);
// Check that the number of captures fit in the static offsets vector buffer.
@@ -2905,7 +2905,7 @@
// csp[0]: Space for the return address placed by DirectCEntryStub.
// csp[8]: Argument 9, the current isolate address.
- __ Mov(x10, Operand(ExternalReference::isolate_address(isolate)));
+ __ Mov(x10, ExternalReference::isolate_address(isolate));
__ Poke(x10, kPointerSize);
Register length = w11;
@@ -2954,8 +2954,7 @@
__ Add(x3, x2, Operand(w10, UXTW));
// Argument 5 (x4): static offsets vector buffer.
- __ Mov(x4,
- Operand(ExternalReference::address_of_static_offsets_vector(isolate)));
+ __ Mov(x4, ExternalReference::address_of_static_offsets_vector(isolate));
// Argument 6 (x5): Set the number of capture registers to zero to force
// global regexps to behave as non-global. This stub is not used for global
@@ -2963,9 +2962,9 @@
__ Mov(x5, 0);
// Argument 7 (x6): Start (high end) of backtracking stack memory area.
- __ Mov(x10, Operand(address_of_regexp_stack_memory_address));
+ __ Mov(x10, address_of_regexp_stack_memory_address);
__ Ldr(x10, MemOperand(x10));
- __ Mov(x11, Operand(address_of_regexp_stack_memory_size));
+ __ Mov(x11, address_of_regexp_stack_memory_size);
__ Ldr(x11, MemOperand(x11));
__ Add(x6, x10, x11);
@@ -3061,7 +3060,7 @@
// and fill the last match info.
ExternalReference address_of_static_offsets_vector =
ExternalReference::address_of_static_offsets_vector(isolate);
- __ Mov(offsets_vector_index, Operand(address_of_static_offsets_vector));
+ __ Mov(offsets_vector_index, address_of_static_offsets_vector);
Label next_capture, done;
// Capture register counter starts from number of capture registers and
@@ -3556,7 +3555,7 @@
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
__ JumpIfNotSmi(code_, &slow_case_);
- __ Cmp(code_, Operand(Smi::FromInt(String::kMaxOneByteCharCode)));
+ __ Cmp(code_, Smi::FromInt(String::kMaxOneByteCharCode));
__ B(hi, &slow_case_);
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
@@ -3906,7 +3905,7 @@
// Preserve some caller-saved registers.
__ Push(x1, x0, lr);
// Push the arguments.
- __ Mov(op, Operand(Smi::FromInt(op_)));
+ __ Mov(op, Smi::FromInt(op_));
__ Push(left, right, op);
// Call the miss handler. This also pops the arguments.
@@ -4255,7 +4254,7 @@
__ B(eq, &check_zero_length);
__ Bind(&strings_not_equal);
- __ Mov(result, Operand(Smi::FromInt(NOT_EQUAL)));
+ __ Mov(result, Smi::FromInt(NOT_EQUAL));
__ Ret();
// Check if the length is zero. If so, the strings must be equal (and empty.)
@@ -4263,7 +4262,7 @@
__ Bind(&check_zero_length);
STATIC_ASSERT(kSmiTag == 0);
__ Cbnz(left_length, &compare_chars);
- __ Mov(result, Operand(Smi::FromInt(EQUAL)));
+ __ Mov(result, Smi::FromInt(EQUAL));
__ Ret();
// Compare characters. Falls through if all characters are equal.
@@ -4272,7 +4271,7 @@
scratch3, &strings_not_equal);
// Characters in strings are equal.
- __ Mov(result, Operand(Smi::FromInt(EQUAL)));
+ __ Mov(result, Smi::FromInt(EQUAL));
__ Ret();
}
@@ -4314,8 +4313,8 @@
__ Bind(&result_not_equal);
Register greater = x10;
Register less = x11;
- __ Mov(greater, Operand(Smi::FromInt(GREATER)));
- __ Mov(less, Operand(Smi::FromInt(LESS)));
+ __ Mov(greater, Smi::FromInt(GREATER));
+ __ Mov(less, Smi::FromInt(LESS));
__ CmovX(result, greater, gt);
__ CmovX(result, less, lt);
__ Ret();
@@ -4441,7 +4440,7 @@
// Get the array's length and calculate new length.
__ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
STATIC_ASSERT(kSmiTag == 0);
- __ Add(length, length, Operand(Smi::FromInt(argc)));
+ __ Add(length, length, Smi::FromInt(argc));
// Check if we could survive without allocation.
__ Ldr(elements_length,
@@ -4568,12 +4567,12 @@
__ Add(end_elements, elements,
Operand::UntagSmiAndScale(length, kPointerSizeLog2));
__ Add(end_elements, end_elements, kEndElementsOffset);
- __ Mov(allocation_top_addr, Operand(new_space_allocation_top));
+ __ Mov(allocation_top_addr, new_space_allocation_top);
__ Ldr(allocation_top, MemOperand(allocation_top_addr));
__ Cmp(end_elements, allocation_top);
__ B(ne, &call_builtin);
- __ Mov(x10, Operand(new_space_allocation_limit));
+ __ Mov(x10, new_space_allocation_limit);
__ Ldr(x10, MemOperand(x10));
__ Add(allocation_top, allocation_top, kAllocationDelta * kPointerSize);
__ Cmp(allocation_top, x10);
@@ -4592,9 +4591,7 @@
// Update elements' and array's sizes.
__ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
- __ Add(elements_length,
- elements_length,
- Operand(Smi::FromInt(kAllocationDelta)));
+ __ Add(elements_length, elements_length, Smi::FromInt(kAllocationDelta));
__ Str(elements_length,
FieldMemOperand(elements, FixedArray::kLengthOffset));
@@ -4693,7 +4690,7 @@
__ Mov(address, regs_.address());
__ Mov(x0, regs_.object());
__ Mov(x1, address);
- __ Mov(x2, Operand(ExternalReference::isolate_address(masm->isolate())));
+ __ Mov(x2, ExternalReference::isolate_address(masm->isolate()));
AllowExternalCallThatCantCauseGC scope(masm);
ExternalReference function =
@@ -4948,7 +4945,7 @@
ExternalReference::BUILTIN_CALL,
masm->isolate())));
// It additionally takes an isolate as a third parameter
- __ Mov(x2, Operand(ExternalReference::isolate_address(masm->isolate())));
+ __ Mov(x2, ExternalReference::isolate_address(masm->isolate()));
#endif
// The caller's return address is above the saved temporaries.
@@ -5335,7 +5332,7 @@
STATIC_ASSERT(AllocationSite::ElementsKindBits::kShift == 0);
__ Ldr(x11, FieldMemOperand(allocation_site,
AllocationSite::kTransitionInfoOffset));
- __ Add(x11, x11, Operand(Smi::FromInt(kFastElementsKindPackedToHoley)));
+ __ Add(x11, x11, Smi::FromInt(kFastElementsKindPackedToHoley));
__ Str(x11, FieldMemOperand(allocation_site,
AllocationSite::kTransitionInfoOffset));
@@ -5617,7 +5614,7 @@
__ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
}
Register isolate_reg = x5;
- __ Mov(isolate_reg, Operand(ExternalReference::isolate_address(isolate)));
+ __ Mov(isolate_reg, ExternalReference::isolate_address(isolate));
// FunctionCallbackArguments:
// return value, return value default, isolate, holder.
diff --git a/src/a64/codegen-a64.cc b/src/a64/codegen-a64.cc
index b7cd5a1..32b3275 100644
--- a/src/a64/codegen-a64.cc
+++ b/src/a64/codegen-a64.cc
@@ -519,7 +519,7 @@
// ExternalReference::InitializeMathExpData().
// Load the address of the start of the array.
- __ Mov(constants, Operand(ExternalReference::math_exp_constants(0)));
+ __ Mov(constants, ExternalReference::math_exp_constants(0));
// We have to do a four-way split here:
// - If input <= about -708.4, the output always rounds to zero.
@@ -595,7 +595,7 @@
__ Add(temp1, temp1, 0x3ff);
// Do the final table lookup.
- __ Mov(temp3, Operand(ExternalReference::math_exp_log_table()));
+ __ Mov(temp3, ExternalReference::math_exp_log_table());
__ Add(temp3, temp3, Operand(temp2, LSL, kDRegSizeLog2));
__ Ldp(temp2.W(), temp3.W(), MemOperand(temp3));
diff --git a/src/a64/debug-a64.cc b/src/a64/debug-a64.cc
index 05c005a..8b901d7 100644
--- a/src/a64/debug-a64.cc
+++ b/src/a64/debug-a64.cc
@@ -202,7 +202,7 @@
__ RecordComment("// Calling from debug break to runtime - come in - over");
#endif
__ Mov(x0, 0); // No arguments.
- __ Mov(x1, Operand(ExternalReference::debug_break(masm->isolate())));
+ __ Mov(x1, ExternalReference::debug_break(masm->isolate()));
CEntryStub stub(1);
__ CallStub(&stub);
@@ -234,7 +234,7 @@
// overwritten by the address of DebugBreakXXX.
ExternalReference after_break_target(Debug_Address::AfterBreakTarget(),
masm->isolate());
- __ Mov(scratch, Operand(after_break_target));
+ __ Mov(scratch, after_break_target);
__ Ldr(scratch, MemOperand(scratch));
__ Br(scratch);
}
diff --git a/src/a64/deoptimizer-a64.cc b/src/a64/deoptimizer-a64.cc
index f3a5fcd..e95cb96 100644
--- a/src/a64/deoptimizer-a64.cc
+++ b/src/a64/deoptimizer-a64.cc
@@ -185,7 +185,7 @@
// - x2: bailout id
// - x3: code object address
// - x4: fp-to-sp delta
- __ Mov(x5, Operand(ExternalReference::isolate_address(isolate())));
+ __ Mov(x5, ExternalReference::isolate_address(isolate()));
{
// Call Deoptimizer::New().
diff --git a/src/a64/full-codegen-a64.cc b/src/a64/full-codegen-a64.cc
index 4f907a5..c95a01a 100644
--- a/src/a64/full-codegen-a64.cc
+++ b/src/a64/full-codegen-a64.cc
@@ -243,7 +243,7 @@
int num_parameters = info->scope()->num_parameters();
int offset = num_parameters * kPointerSize;
__ Add(x2, fp, StandardFrameConstants::kCallerSPOffset + offset);
- __ Mov(x1, Operand(Smi::FromInt(num_parameters)));
+ __ Mov(x1, Smi::FromInt(num_parameters));
__ Push(x3, x2, x1);
// Arguments to ArgumentsAccessStub:
@@ -322,14 +322,14 @@
void FullCodeGenerator::ClearAccumulator() {
- __ Mov(x0, Operand(Smi::FromInt(0)));
+ __ Mov(x0, Smi::FromInt(0));
}
void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
__ Mov(x2, Operand(profiling_counter_));
__ Ldr(x3, FieldMemOperand(x2, Cell::kValueOffset));
- __ Subs(x3, x3, Operand(Smi::FromInt(delta)));
+ __ Subs(x3, x3, Smi::FromInt(delta));
__ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
}
@@ -341,7 +341,7 @@
reset_value = FLAG_interrupt_budget >> 4;
}
__ Mov(x2, Operand(profiling_counter_));
- __ Mov(x3, Operand(Smi::FromInt(reset_value)));
+ __ Mov(x3, Smi::FromInt(reset_value));
__ Str(x3, FieldMemOperand(x2, Cell::kValueOffset));
}
@@ -831,7 +831,7 @@
ASSERT(IsDeclaredVariableMode(mode));
PropertyAttributes attr = IsImmutableVariableMode(mode) ? READ_ONLY
: NONE;
- __ Mov(x1, Operand(Smi::FromInt(attr)));
+ __ Mov(x1, Smi::FromInt(attr));
// Push initial value, if any.
// Note: For variables we must not push an initial value (such as
// 'undefined') because we may have a (legal) redeclaration and we
@@ -895,7 +895,7 @@
case Variable::LOOKUP: {
Comment cmnt(masm_, "[ Function Declaration");
__ Mov(x2, Operand(variable->name()));
- __ Mov(x1, Operand(Smi::FromInt(NONE)));
+ __ Mov(x1, Smi::FromInt(NONE));
__ Push(cp, x2, x1);
// Push initial value for function declaration.
VisitForStackValue(declaration->fun());
@@ -971,7 +971,7 @@
Register flags = xzr;
if (Smi::FromInt(DeclareGlobalsFlags())) {
flags = x10;
- __ Mov(flags, Operand(Smi::FromInt(DeclareGlobalsFlags())));
+ __ Mov(flags, Smi::FromInt(DeclareGlobalsFlags()));
}
__ Push(cp, x11, flags);
__ CallRuntime(Runtime::kDeclareGlobals, 3);
@@ -1150,7 +1150,7 @@
// Set up the four remaining stack slots.
__ Push(x0); // Map.
- __ Mov(x0, Operand(Smi::FromInt(0)));
+ __ Mov(x0, Smi::FromInt(0));
// Push enumeration cache, enumeration cache length (as smi) and zero.
__ SmiTag(x1);
__ Push(x2, x1, x0);
@@ -1168,10 +1168,10 @@
isolate());
StoreFeedbackVectorSlot(slot, feedback);
__ LoadObject(x1, FeedbackVector());
- __ Mov(x10, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
+ __ Mov(x10, Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker));
__ Str(x10, FieldMemOperand(x1, FixedArray::OffsetOfElementAt(slot)));
- __ Mov(x1, Operand(Smi::FromInt(1))); // Smi indicates slow check.
+ __ Mov(x1, Smi::FromInt(1)); // Smi indicates slow check.
__ Peek(x10, 0); // Get enumerated object.
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
// TODO(all): similar check was done already. Can we avoid it here?
@@ -1237,7 +1237,7 @@
__ Bind(loop_statement.continue_label());
// TODO(all): We could use a callee saved register to avoid popping.
__ Pop(x0);
- __ Add(x0, x0, Operand(Smi::FromInt(1)));
+ __ Add(x0, x0, Smi::FromInt(1));
__ Push(x0);
EmitBackEdgeBookkeeping(stmt, &loop);
@@ -1582,7 +1582,7 @@
// Create regexp literal using runtime function.
// Result will be in x0.
- __ Mov(x3, Operand(Smi::FromInt(expr->literal_index())));
+ __ Mov(x3, Smi::FromInt(expr->literal_index()));
__ Mov(x2, Operand(expr->pattern()));
__ Mov(x1, Operand(expr->flags()));
__ Push(x4, x3, x2, x1);
@@ -1596,7 +1596,7 @@
__ B(&allocated);
__ Bind(&runtime_allocate);
- __ Mov(x10, Operand(Smi::FromInt(size)));
+ __ Mov(x10, Smi::FromInt(size));
__ Push(x5, x10);
__ CallRuntime(Runtime::kAllocateInNewSpace, 1);
__ Pop(x5);
@@ -1628,7 +1628,7 @@
Handle<FixedArray> constant_properties = expr->constant_properties();
__ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
- __ Mov(x2, Operand(Smi::FromInt(expr->literal_index())));
+ __ Mov(x2, Smi::FromInt(expr->literal_index()));
__ Mov(x1, Operand(constant_properties));
int flags = expr->fast_elements()
? ObjectLiteral::kFastElements
@@ -1636,7 +1636,7 @@
flags |= expr->has_function()
? ObjectLiteral::kHasFunction
: ObjectLiteral::kNoFlags;
- __ Mov(x0, Operand(Smi::FromInt(flags)));
+ __ Mov(x0, Smi::FromInt(flags));
int properties_count = constant_properties->length() / 2;
const int max_cloned_properties =
FastCloneShallowObjectStub::kMaximumClonedProperties;
@@ -1695,7 +1695,7 @@
__ Push(x0);
VisitForStackValue(key);
VisitForStackValue(value);
- __ Mov(x0, Operand(Smi::FromInt(NONE))); // PropertyAttributes
+ __ Mov(x0, Smi::FromInt(NONE)); // PropertyAttributes
__ Push(x0);
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
@@ -1733,7 +1733,7 @@
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
- __ Mov(x10, Operand(Smi::FromInt(NONE)));
+ __ Mov(x10, Smi::FromInt(NONE));
__ Push(x10);
__ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
}
@@ -1779,8 +1779,7 @@
__ Ldr(x3, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
__ Ldr(x3, FieldMemOperand(x3, JSFunction::kLiteralsOffset));
- // TODO(jbramley): Can these Operand constructors be implicit?
- __ Mov(x2, Operand(Smi::FromInt(expr->literal_index())));
+ __ Mov(x2, Smi::FromInt(expr->literal_index()));
__ Mov(x1, Operand(constant_elements));
if (has_fast_elements && constant_elements_values->map() ==
isolate()->heap()->fixed_cow_array_map()) {
@@ -1793,7 +1792,7 @@
isolate()->counters()->cow_arrays_created_stub(), 1, x10, x11);
} else if ((expr->depth() > 1) || Serializer::enabled() ||
length > FastCloneShallowArrayStub::kMaximumClonedLength) {
- __ Mov(x0, Operand(Smi::FromInt(flags)));
+ __ Mov(x0, Smi::FromInt(flags));
__ Push(x3, x2, x1, x0);
__ CallRuntime(Runtime::kCreateArrayLiteral, 4);
} else {
@@ -1837,7 +1836,7 @@
kLRHasBeenSaved, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
} else {
- __ Mov(x3, Operand(Smi::FromInt(i)));
+ __ Mov(x3, Smi::FromInt(i));
StoreArrayLiteralElementStub stub;
__ CallStub(&stub);
}
@@ -2160,7 +2159,7 @@
void FullCodeGenerator::EmitCallStoreContextSlot(
Handle<String> name, StrictMode strict_mode) {
__ Mov(x11, Operand(name));
- __ Mov(x10, Operand(Smi::FromInt(strict_mode)));
+ __ Mov(x10, Smi::FromInt(strict_mode));
// jssp[0] : mode.
// jssp[8] : name.
// jssp[16] : context.
@@ -2410,7 +2409,7 @@
TypeFeedbackInfo::UninitializedSentinel(isolate());
StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
__ LoadObject(x2, FeedbackVector());
- __ Mov(x3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
+ __ Mov(x3, Smi::FromInt(expr->CallFeedbackSlot()));
// Record call targets in unoptimized code.
CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
@@ -2441,9 +2440,9 @@
__ Push(x10, x11);
// Prepare to push the language mode.
- __ Mov(x10, Operand(Smi::FromInt(strict_mode())));
+ __ Mov(x10, 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())));
+ __ Mov(x11, Smi::FromInt(scope()->start_position()));
// Push.
__ Push(x10, x11);
@@ -2616,7 +2615,7 @@
}
__ LoadObject(x2, FeedbackVector());
- __ Mov(x3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
+ __ Mov(x3, Smi::FromInt(expr->CallNewFeedbackSlot()));
CallConstructStub stub(RECORD_CALL_TARGET);
__ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
@@ -2955,14 +2954,14 @@
// Skip the arguments adaptor frame if it exists.
Label check_frame_marker;
__ Ldr(x1, MemOperand(x2, StandardFrameConstants::kContextOffset));
- __ Cmp(x1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(x1, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ B(ne, &check_frame_marker);
__ Ldr(x2, MemOperand(x2, StandardFrameConstants::kCallerFPOffset));
// Check the marker in the calling frame.
__ Bind(&check_frame_marker);
__ Ldr(x1, MemOperand(x2, StandardFrameConstants::kMarkerOffset));
- __ Cmp(x1, Operand(Smi::FromInt(StackFrame::CONSTRUCT)));
+ __ Cmp(x1, Smi::FromInt(StackFrame::CONSTRUCT));
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
Split(eq, if_true, if_false, fall_through);
@@ -3001,7 +3000,7 @@
// ArgumentsAccessStub expects the key in x1.
VisitForAccumulatorValue(args->at(0));
__ Mov(x1, x0);
- __ Mov(x0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
+ __ Mov(x0, Smi::FromInt(info_->scope()->num_parameters()));
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
__ CallStub(&stub);
context()->Plug(x0);
@@ -3012,12 +3011,12 @@
ASSERT(expr->arguments()->length() == 0);
Label exit;
// Get the number of formal parameters.
- __ Mov(x0, Operand(Smi::FromInt(info_->scope()->num_parameters())));
+ __ Mov(x0, Smi::FromInt(info_->scope()->num_parameters()));
// Check if the calling frame is an arguments adaptor frame.
__ Ldr(x12, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ Ldr(x13, MemOperand(x12, StandardFrameConstants::kContextOffset));
- __ Cmp(x13, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(x13, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ B(ne, &exit);
// Arguments adaptor case: Read the arguments length from the
@@ -3183,7 +3182,7 @@
} else {
if (index->value() < JSDate::kFirstUncachedField) {
ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
- __ Mov(x10, Operand(stamp));
+ __ Mov(x10, stamp);
__ Ldr(stamp_addr, MemOperand(x10));
__ Ldr(stamp_cache, FieldMemOperand(object, JSDate::kCacheStampOffset));
__ Cmp(stamp_addr, stamp_cache);
@@ -3194,7 +3193,7 @@
}
__ Bind(&runtime);
- __ Mov(x1, Operand(index));
+ __ Mov(x1, index);
__ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
__ B(&done);
}
@@ -3422,7 +3421,7 @@
__ Bind(&need_conversion);
// Move smi zero into the result register, which will trigger conversion.
- __ Mov(result, Operand(Smi::FromInt(0)));
+ __ Mov(result, Smi::FromInt(0));
__ B(&done);
NopRuntimeCallHelper call_helper;
@@ -3675,7 +3674,7 @@
// element: Current array element.
// elements_end: Array end.
if (FLAG_debug_code) {
- __ Cmp(array_length, Operand(0));
+ __ Cmp(array_length, 0);
__ Assert(gt, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
}
__ Bind(&loop);
@@ -3888,7 +3887,7 @@
if (property != NULL) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- __ Mov(x10, Operand(Smi::FromInt(strict_mode())));
+ __ Mov(x10, Smi::FromInt(strict_mode()));
__ Push(x10);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(x0);
@@ -3900,7 +3899,7 @@
if (var->IsUnallocated()) {
__ Ldr(x12, GlobalObjectMemOperand());
__ Mov(x11, Operand(var->name()));
- __ Mov(x10, Operand(Smi::FromInt(SLOPPY)));
+ __ Mov(x10, Smi::FromInt(SLOPPY));
__ Push(x12, x11, x10);
__ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
context()->Plug(x0);
@@ -4068,10 +4067,10 @@
}
}
- __ Adds(x0, x0, Operand(Smi::FromInt(count_value)));
+ __ Adds(x0, x0, Smi::FromInt(count_value));
__ B(vc, &done);
// Call stub. Undo operation first.
- __ Sub(x0, x0, Operand(Smi::FromInt(count_value)));
+ __ Sub(x0, x0, Smi::FromInt(count_value));
__ B(&stub_call);
__ Bind(&slow);
}
@@ -4100,7 +4099,7 @@
__ Bind(&stub_call);
__ Mov(x1, x0);
- __ Mov(x0, Operand(Smi::FromInt(count_value)));
+ __ Mov(x0, Smi::FromInt(count_value));
// Record position before stub call.
SetSourcePosition(expr->position());
@@ -4434,7 +4433,7 @@
__ Bind(&suspend);
VisitForAccumulatorValue(expr->generator_object());
ASSERT((continuation.pos() > 0) && Smi::IsValid(continuation.pos()));
- __ Mov(x1, Operand(Smi::FromInt(continuation.pos())));
+ __ Mov(x1, Smi::FromInt(continuation.pos()));
__ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset));
__ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset));
__ Mov(x1, cp);
@@ -4457,7 +4456,7 @@
case Yield::FINAL: {
VisitForAccumulatorValue(expr->generator_object());
- __ Mov(x1, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorClosed)));
+ __ Mov(x1, Smi::FromInt(JSGeneratorObject::kGeneratorClosed));
__ Str(x1, FieldMemOperand(result_register(),
JSGeneratorObject::kContinuationOffset));
// Pop value from top-of-stack slot, box result into result register.
@@ -4509,7 +4508,7 @@
__ Peek(x0, generator_object_depth);
__ Push(x0); // g
ASSERT((l_continuation.pos() > 0) && Smi::IsValid(l_continuation.pos()));
- __ Mov(x1, Operand(Smi::FromInt(l_continuation.pos())));
+ __ Mov(x1, Smi::FromInt(l_continuation.pos()));
__ Str(x1, FieldMemOperand(x0, JSGeneratorObject::kContinuationOffset));
__ Str(cp, FieldMemOperand(x0, JSGeneratorObject::kContextOffset));
__ Mov(x1, cp);
@@ -4587,8 +4586,8 @@
JSGeneratorObject::kContinuationOffset));
STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting < 0);
STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed == 0);
- __ CompareAndBranch(x10, Operand(Smi::FromInt(0)), eq, &closed_state);
- __ CompareAndBranch(x10, Operand(Smi::FromInt(0)), lt, &wrong_state);
+ __ CompareAndBranch(x10, Smi::FromInt(0), eq, &closed_state);
+ __ CompareAndBranch(x10, Smi::FromInt(0), lt, &wrong_state);
// Load suspended function and context.
__ Ldr(cp, FieldMemOperand(generator_object,
@@ -4642,7 +4641,7 @@
UntagSmiFieldMemOperand(generator_object,
JSGeneratorObject::kContinuationOffset));
__ Add(x10, x10, x11);
- __ Mov(x12, Operand(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting)));
+ __ Mov(x12, Smi::FromInt(JSGeneratorObject::kGeneratorExecuting));
__ Str(x12, FieldMemOperand(generator_object,
JSGeneratorObject::kContinuationOffset));
__ Br(x10);
@@ -4654,7 +4653,7 @@
// up the stack and the handlers.
__ PushMultipleTimes(the_hole, operand_stack_size);
- __ Mov(x10, Operand(Smi::FromInt(resume_mode)));
+ __ Mov(x10, Smi::FromInt(resume_mode));
__ Push(generator_object, result_register(), x10);
__ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
// Not reached: the runtime call returns elsewhere.
@@ -4798,12 +4797,12 @@
// Store pending message while executing finally block.
ExternalReference pending_message_obj =
ExternalReference::address_of_pending_message_obj(isolate());
- __ Mov(x10, Operand(pending_message_obj));
+ __ Mov(x10, pending_message_obj);
__ Ldr(x10, MemOperand(x10));
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
- __ Mov(x11, Operand(has_pending_message));
+ __ Mov(x11, has_pending_message);
__ Ldr(x11, MemOperand(x11));
__ SmiTag(x11);
@@ -4811,7 +4810,7 @@
ExternalReference pending_message_script =
ExternalReference::address_of_pending_message_script(isolate());
- __ Mov(x10, Operand(pending_message_script));
+ __ Mov(x10, pending_message_script);
__ Ldr(x10, MemOperand(x10));
__ Push(x10);
}
@@ -4825,18 +4824,18 @@
__ Pop(x10, x11, x12);
ExternalReference pending_message_script =
ExternalReference::address_of_pending_message_script(isolate());
- __ Mov(x13, Operand(pending_message_script));
+ __ Mov(x13, pending_message_script);
__ Str(x10, MemOperand(x13));
__ SmiUntag(x11);
ExternalReference has_pending_message =
ExternalReference::address_of_has_pending_message(isolate());
- __ Mov(x13, Operand(has_pending_message));
+ __ Mov(x13, has_pending_message);
__ Str(x11, MemOperand(x13));
ExternalReference pending_message_obj =
ExternalReference::address_of_pending_message_obj(isolate());
- __ Mov(x13, Operand(pending_message_obj));
+ __ Mov(x13, pending_message_obj);
__ Str(x12, MemOperand(x13));
// Restore result register and cooked return address from the stack.
diff --git a/src/a64/ic-a64.cc b/src/a64/ic-a64.cc
index 71d4c66..49b36af 100644
--- a/src/a64/ic-a64.cc
+++ b/src/a64/ic-a64.cc
@@ -141,7 +141,7 @@
NameDictionary::kElementsStartIndex * kPointerSize;
static const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
__ Ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
- __ Tst(scratch1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
+ __ Tst(scratch1, Smi::FromInt(PropertyDetails::TypeField::kMask));
__ B(ne, miss);
// Get the value at the masked, scaled index and return.
@@ -376,7 +376,7 @@
// Check if element is in the range of mapped arguments. If not, jump
// to the unmapped lookup.
__ Ldr(scratch1, FieldMemOperand(map, FixedArray::kLengthOffset));
- __ Sub(scratch1, scratch1, Operand(Smi::FromInt(2)));
+ __ Sub(scratch1, scratch1, Smi::FromInt(2));
__ Cmp(key, scratch1);
__ B(hs, unmapped_case);
@@ -702,7 +702,7 @@
ExternalReference cache_keys =
ExternalReference::keyed_lookup_cache_keys(isolate);
- __ Mov(scratch3, Operand(cache_keys));
+ __ Mov(scratch3, cache_keys);
__ Add(scratch3, scratch3, Operand(scratch2, LSL, kPointerSizeLog2 + 1));
for (int i = 0; i < kEntriesPerBucket - 1; i++) {
@@ -732,7 +732,7 @@
// Hit on nth entry.
for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
__ Bind(&hit_on_nth_entry[i]);
- __ Mov(scratch3, Operand(cache_field_offsets));
+ __ Mov(scratch3, cache_field_offsets);
if (i != 0) {
__ Add(scratch2, scratch2, i);
}
@@ -939,7 +939,7 @@
// Push PropertyAttributes(NONE) and strict_mode for runtime call.
STATIC_ASSERT(NONE == 0);
- __ Mov(x10, Operand(Smi::FromInt(strict_mode)));
+ __ Mov(x10, Smi::FromInt(strict_mode));
__ Push(xzr, x10);
__ TailCallRuntime(Runtime::kSetProperty, 5, 1);
@@ -996,7 +996,7 @@
__ Bind(&finish_store);
if (increment_length == kIncrementLength) {
// Add 1 to receiver->length.
- __ Add(x10, key, Operand(Smi::FromInt(1)));
+ __ Add(x10, key, Smi::FromInt(1));
__ Str(x10, FieldMemOperand(receiver, JSArray::kLengthOffset));
}
@@ -1048,7 +1048,7 @@
&transition_double_elements);
if (increment_length == kIncrementLength) {
// Add 1 to receiver->length.
- __ Add(x10, key, Operand(Smi::FromInt(1)));
+ __ Add(x10, key, Smi::FromInt(1));
__ Str(x10, FieldMemOperand(receiver, JSArray::kLengthOffset));
}
__ Ret();
@@ -1285,8 +1285,8 @@
__ Push(x1, x2, x0);
- __ Mov(x11, Operand(Smi::FromInt(NONE))); // PropertyAttributes
- __ Mov(x10, Operand(Smi::FromInt(strict_mode)));
+ __ Mov(x11, Smi::FromInt(NONE)); // PropertyAttributes
+ __ Mov(x10, Smi::FromInt(strict_mode));
__ Push(x11, x10);
// Do tail-call to runtime routine.
diff --git a/src/a64/lithium-a64.cc b/src/a64/lithium-a64.cc
index 1c3b24e..c550101 100644
--- a/src/a64/lithium-a64.cc
+++ b/src/a64/lithium-a64.cc
@@ -1762,12 +1762,17 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
- return can_deopt ? AssignEnvironment(result) : result;
+ LOperand* temp =
+ ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
+ NULL : TempRegister();
+ LInstruction* result = DefineAsRegister(
+ new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
@@ -1784,8 +1789,8 @@
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
if (instr->RightIsPowerOf2()) {
return DoFlooringDivByPowerOf2I(instr);
- } else if (false && instr->right()->IsConstant()) {
- return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable.
+ } else if (instr->right()->IsConstant()) {
+ return DoFlooringDivByConstI(instr);
} else {
return DoFlooringDivI(instr);
}
diff --git a/src/a64/lithium-a64.h b/src/a64/lithium-a64.h
index a100da8..1bd1b80 100644
--- a/src/a64/lithium-a64.h
+++ b/src/a64/lithium-a64.h
@@ -1956,16 +1956,17 @@
};
-class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
public:
- LFlooringDivByConstI(LOperand* dividend, int32_t divisor) {
+ LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
inputs_[0] = dividend;
divisor_ = divisor;
+ temps_[0] = temp;
}
LOperand* dividend() { return inputs_[0]; }
int32_t divisor() const { return divisor_; }
- LOperand* temp1() { return temps_[0]; }
+ LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
diff --git a/src/a64/lithium-codegen-a64.cc b/src/a64/lithium-codegen-a64.cc
index f67eefa..060c1da 100644
--- a/src/a64/lithium-codegen-a64.cc
+++ b/src/a64/lithium-codegen-a64.cc
@@ -801,7 +801,7 @@
ASSERT(info()->IsStub());
frame_is_built_ = true;
__ Push(lr, fp, cp);
- __ Mov(fp, Operand(Smi::FromInt(StackFrame::STUB)));
+ __ Mov(fp, Smi::FromInt(StackFrame::STUB));
__ Push(fp);
__ Add(fp, __ StackPointer(),
StandardFrameConstants::kFixedFrameSizeFromFp);
@@ -855,8 +855,7 @@
Register stub_deopt_entry = temps.AcquireX();
Register stub_marker = temps.AcquireX();
- __ Mov(stub_deopt_entry,
- Operand(ExternalReference::ForDeoptEntry(entry)));
+ __ Mov(stub_deopt_entry, ExternalReference::ForDeoptEntry(entry));
if (needs_frame.is_bound()) {
__ B(&needs_frame);
} else {
@@ -865,7 +864,7 @@
// have a function pointer to install in the stack frame that we're
// building, install a special marker there instead.
ASSERT(info()->IsStub());
- __ Mov(stub_marker, Operand(Smi::FromInt(StackFrame::STUB)));
+ __ Mov(stub_marker, Smi::FromInt(StackFrame::STUB));
__ Push(lr, fp, cp, stub_marker);
__ Add(fp, __ StackPointer(), 2 * kPointerSize);
__ Call(stub_deopt_entry);
@@ -1005,7 +1004,7 @@
__ Push(x0, x1, x2);
__ Mrs(x2, NZCV);
- __ Mov(x0, Operand(count));
+ __ Mov(x0, count);
__ Ldr(w1, MemOperand(x0));
__ Subs(x1, x1, 1);
__ B(gt, ¬_zero);
@@ -1552,13 +1551,13 @@
// TODO(3095996): Get rid of this. For now, we need to make the
// result register contain a valid pointer because it is already
// contained in the register pointer map.
- __ Mov(ToRegister(instr->result()), Operand(Smi::FromInt(0)));
+ __ Mov(ToRegister(instr->result()), Smi::FromInt(0));
PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
// We're in a SafepointRegistersScope so we can use any scratch registers.
Register size = x0;
if (instr->size()->IsConstantOperand()) {
- __ Mov(size, Operand(ToSmi(LConstantOperand::cast(instr->size()))));
+ __ Mov(size, ToSmi(LConstantOperand::cast(instr->size())));
} else {
__ SmiTag(size, ToRegister32(instr->size()).X());
}
@@ -1574,7 +1573,7 @@
} else {
flags = AllocateTargetSpace::update(flags, NEW_SPACE);
}
- __ Mov(x10, Operand(Smi::FromInt(flags)));
+ __ Mov(x10, Smi::FromInt(flags));
__ Push(size, x10);
CallRuntimeFromDeferred(
@@ -1654,7 +1653,7 @@
MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
__ Ldr(result,
MemOperand(previous_fp, StandardFrameConstants::kContextOffset));
- __ Cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ Csel(result, fp, previous_fp, ne);
}
}
@@ -1779,9 +1778,9 @@
ToInteger32(LConstantOperand::cast(instr->index()));
if (instr->hydrogen()->length()->representation().IsSmi()) {
- __ Cmp(length, Operand(Smi::FromInt(constant_index)));
+ __ Cmp(length, Smi::FromInt(constant_index));
} else {
- __ Cmp(length, Operand(constant_index));
+ __ Cmp(length, constant_index);
}
} else {
ASSERT(instr->hydrogen()->index()->representation().IsInteger32());
@@ -1819,7 +1818,7 @@
EmitBranch(instr, eq);
} else if (type.IsSmi()) {
ASSERT(!info()->IsStub());
- EmitCompareAndBranch(instr, ne, value, Operand(Smi::FromInt(0)));
+ EmitCompareAndBranch(instr, ne, value, Smi::FromInt(0));
} else if (type.IsJSArray()) {
ASSERT(!info()->IsStub());
EmitGoto(instr->TrueDestination(chunk()));
@@ -3029,7 +3028,7 @@
Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
__ LoadRelocated(scratch, Operand(Handle<Object>(cell)));
__ ldr(scratch, FieldMemOperand(scratch, PropertyCell::kValueOffset));
- __ cmp(map, Operand(scratch));
+ __ cmp(map, scratch);
__ b(&cache_miss, ne);
// The address of this instruction is computed relative to the map check
// above, so check the size of the code generated.
@@ -3141,7 +3140,7 @@
// Skip the arguments adaptor frame if it exists.
Label check_frame_marker;
__ Ldr(temp2, MemOperand(temp1, StandardFrameConstants::kContextOffset));
- __ Cmp(temp2, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ Cmp(temp2, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ B(ne, &check_frame_marker);
__ Ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset));
@@ -3892,8 +3891,31 @@
DeoptimizeIf(eq, instr->environment());
}
- // TODO(svenpanne) Add correction terms.
- __ TruncatingDiv(result, dividend, divisor);
+ // Easy case: We need no dynamic check for the dividend and the flooring
+ // division is the same as the truncating division.
+ if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
+ __ TruncatingDiv(result, dividend, Abs(divisor));
+ if (divisor < 0) __ Neg(result, result);
+ return;
+ }
+
+ // In the general case we may need to adjust before and after the truncating
+ // division to get a flooring division.
+ Register temp = ToRegister32(instr->temp());
+ ASSERT(!AreAliased(temp, dividend, result));
+ Label needs_adjustment, done;
+ __ Cmp(dividend, 0);
+ __ B(divisor > 0 ? lt : gt, &needs_adjustment);
+ __ TruncatingDiv(result, dividend, Abs(divisor));
+ if (divisor < 0) __ Neg(result, result);
+ __ B(&done);
+ __ bind(&needs_adjustment);
+ __ Add(temp, dividend, Operand(divisor > 0 ? 1 : -1));
+ __ TruncatingDiv(result, temp, Abs(divisor));
+ if (divisor < 0) __ Neg(result, result);
+ __ Sub(result, result, Operand(1));
+ __ bind(&done);
}
@@ -4027,7 +4049,6 @@
DoubleRegister temp1 = ToDoubleRegister(instr->temp1());
Register result = ToRegister(instr->result());
Label try_rounding;
- Label deopt;
Label done;
// Math.round() rounds to the nearest integer, with ties going towards
@@ -4049,8 +4070,7 @@
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ Fmov(result, input);
- __ Cmp(result, 0);
- DeoptimizeIf(mi, instr->environment()); // [-0.5, -0.0].
+ DeoptimizeIfNegative(result, instr->environment()); // [-0.5, -0.0].
}
__ Fcmp(input, dot_five);
__ Mov(result, 1); // +0.5.
@@ -4059,9 +4079,6 @@
__ Csel(result, result, xzr, eq);
__ B(&done);
- __ Bind(&deopt);
- Deoptimize(instr->environment());
-
__ Bind(&try_rounding);
// Since we're providing a 32-bit result, we can implement ties-to-infinity by
// adding 0.5 to the input, then taking the floor of the result. This does not
@@ -4076,7 +4093,7 @@
// * the result is not representable using a 32-bit integer.
__ Fcmp(input, 0.0);
__ Ccmp(result, Operand(result.W(), SXTW), NoFlag, vc);
- __ B(ne, &deopt);
+ DeoptimizeIf(ne, instr->environment());
__ Bind(&done);
}
@@ -4140,7 +4157,7 @@
__ B(pl, ÷nd_is_not_negative);
// Note that this is correct even for kMinInt operands.
__ Neg(dividend, dividend);
- __ And(dividend, dividend, Operand(mask));
+ __ And(dividend, dividend, mask);
__ Negs(dividend, dividend);
if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
DeoptimizeIf(eq, instr->environment());
@@ -4149,7 +4166,7 @@
}
__ bind(÷nd_is_not_negative);
- __ And(dividend, dividend, Operand(mask));
+ __ And(dividend, dividend, mask);
__ bind(&done);
}
@@ -4879,7 +4896,7 @@
// TODO(all): if Mov could handle object in new space then it could be used
// here.
__ LoadHeapObject(scratch1, instr->hydrogen()->pairs());
- __ Mov(scratch2, Operand(Smi::FromInt(instr->hydrogen()->flags())));
+ __ Mov(scratch2, Smi::FromInt(instr->hydrogen()->flags()));
__ Push(cp, scratch1, scratch2); // The context is the first argument.
CallRuntime(Runtime::kDeclareGlobals, 3, instr);
}
@@ -5592,7 +5609,7 @@
__ B(&allocated);
__ Bind(&runtime_allocate);
- __ Mov(x0, Operand(Smi::FromInt(size)));
+ __ Mov(x0, Smi::FromInt(size));
__ Push(x1, x0);
CallRuntime(Runtime::kAllocateInNewSpace, 1, instr);
__ Pop(x1);
@@ -5826,7 +5843,7 @@
__ AssertSmi(index);
Label out_of_object, done;
- __ Cmp(index, Operand(Smi::FromInt(0)));
+ __ Cmp(index, Smi::FromInt(0));
__ B(lt, &out_of_object);
STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
diff --git a/src/a64/lithium-gap-resolver-a64.cc b/src/a64/lithium-gap-resolver-a64.cc
index 3087a3e..a92ef85 100644
--- a/src/a64/lithium-gap-resolver-a64.cc
+++ b/src/a64/lithium-gap-resolver-a64.cc
@@ -257,7 +257,7 @@
if (destination->IsRegister()) {
Register dst = cgen_->ToRegister(destination);
if (cgen_->IsSmi(constant_source)) {
- __ Mov(dst, Operand(cgen_->ToSmi(constant_source)));
+ __ Mov(dst, cgen_->ToSmi(constant_source));
} else if (cgen_->IsInteger32Constant(constant_source)) {
__ Mov(dst, cgen_->ToInteger32(constant_source));
} else {
@@ -271,7 +271,7 @@
ASSERT(!in_cycle_); // Constant moves happen after all cycles are gone.
need_to_restore_root_ = true;
if (cgen_->IsSmi(constant_source)) {
- __ Mov(kSavedValue, Operand(cgen_->ToSmi(constant_source)));
+ __ Mov(kSavedValue, cgen_->ToSmi(constant_source));
} else if (cgen_->IsInteger32Constant(constant_source)) {
__ Mov(kSavedValue, cgen_->ToInteger32(constant_source));
} else {
diff --git a/src/a64/macro-assembler-a64.cc b/src/a64/macro-assembler-a64.cc
index 1fad909..851f10a 100644
--- a/src/a64/macro-assembler-a64.cc
+++ b/src/a64/macro-assembler-a64.cc
@@ -1253,7 +1253,7 @@
void MacroAssembler::EnumLengthSmi(Register dst, Register map) {
STATIC_ASSERT(Map::EnumLengthBits::kShift == 0);
Ldr(dst, FieldMemOperand(map, Map::kBitField3Offset));
- And(dst, dst, Operand(Smi::FromInt(Map::EnumLengthBits::kMask)));
+ And(dst, dst, Smi::FromInt(Map::EnumLengthBits::kMask));
}
@@ -1326,10 +1326,10 @@
Add(scratch1, receiver,
JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag);
- Cmp(scratch1, Operand(new_space_start));
+ Cmp(scratch1, new_space_start);
B(lt, no_memento_found);
- Mov(scratch2, Operand(new_space_allocation_top));
+ Mov(scratch2, new_space_allocation_top);
Ldr(scratch2, MemOperand(scratch2));
Cmp(scratch1, scratch2);
B(gt, no_memento_found);
@@ -1367,8 +1367,8 @@
ASSERT(cond == eq || cond == ne);
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
- And(temp, object, Operand(ExternalReference::new_space_mask(isolate())));
- Cmp(temp, Operand(ExternalReference::new_space_start(isolate())));
+ And(temp, object, ExternalReference::new_space_mask(isolate()));
+ Cmp(temp, ExternalReference::new_space_start(isolate()));
B(cond, branch);
}
@@ -1471,7 +1471,7 @@
RecordComment((msg != NULL) ? msg : "UNKNOWN");
#endif
- Mov(x0, Operand(Smi::FromInt(reason)));
+ Mov(x0, Smi::FromInt(reason));
Push(x0);
// Disable stub call restrictions to always allow calls to throw.
@@ -1600,7 +1600,7 @@
// Place the necessary arguments.
Mov(x0, num_arguments);
- Mov(x1, Operand(ExternalReference(f, isolate())));
+ Mov(x1, ExternalReference(f, isolate()));
CEntryStub stub(1, save_doubles);
CallStub(&stub);
@@ -1639,7 +1639,7 @@
Mov(x10, reinterpret_cast<uintptr_t>(is_profiling_flag));
Ldrb(w10, MemOperand(x10));
Cbz(w10, &profiler_disabled);
- Mov(x3, Operand(thunk_ref));
+ Mov(x3, thunk_ref);
B(&end_profiler_check);
Bind(&profiler_disabled);
@@ -1662,7 +1662,7 @@
Register limit_reg = x20;
Register level_reg = w21;
- Mov(handle_scope_base, Operand(next_address));
+ Mov(handle_scope_base, next_address);
Ldr(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
Ldr(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
Ldr(level_reg, MemOperand(handle_scope_base, kLevelOffset));
@@ -1672,7 +1672,7 @@
if (FLAG_log_timer_events) {
FrameScope frame(this, StackFrame::MANUAL);
PushSafepointRegisters();
- Mov(x0, Operand(ExternalReference::isolate_address(isolate())));
+ Mov(x0, ExternalReference::isolate_address(isolate()));
CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
PopSafepointRegisters();
}
@@ -1686,7 +1686,7 @@
if (FLAG_log_timer_events) {
FrameScope frame(this, StackFrame::MANUAL);
PushSafepointRegisters();
- Mov(x0, Operand(ExternalReference::isolate_address(isolate())));
+ Mov(x0, ExternalReference::isolate_address(isolate()));
CallCFunction(ExternalReference::log_leave_external_function(isolate()), 1);
PopSafepointRegisters();
}
@@ -1722,7 +1722,7 @@
Peek(x22, (spill_offset + 3) * kXRegSize);
// Check if the function scheduled an exception.
- Mov(x5, Operand(ExternalReference::scheduled_exception_address(isolate())));
+ Mov(x5, ExternalReference::scheduled_exception_address(isolate()));
Ldr(x5, MemOperand(x5));
JumpIfNotRoot(x5, Heap::kTheHoleValueRootIndex, &promote_scheduled_exception);
Bind(&exception_handled);
@@ -1750,7 +1750,7 @@
// Save the return value in a callee-save register.
Register saved_result = x19;
Mov(saved_result, x0);
- Mov(x0, Operand(ExternalReference::isolate_address(isolate())));
+ Mov(x0, ExternalReference::isolate_address(isolate()));
CallCFunction(
ExternalReference::delete_handle_scope_extensions(isolate()), 1);
Mov(x0, saved_result);
@@ -1761,7 +1761,7 @@
void MacroAssembler::CallExternalReference(const ExternalReference& ext,
int num_arguments) {
Mov(x0, num_arguments);
- Mov(x1, Operand(ext));
+ Mov(x1, ext);
CEntryStub stub(1);
CallStub(&stub);
@@ -1769,7 +1769,7 @@
void MacroAssembler::JumpToExternalReference(const ExternalReference& builtin) {
- Mov(x1, Operand(builtin));
+ Mov(x1, builtin);
CEntryStub stub(1);
Jump(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
}
@@ -1881,7 +1881,7 @@
int num_of_double_args) {
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
- Mov(temp, Operand(function));
+ Mov(temp, function);
CallCFunction(temp, num_of_reg_args, num_of_double_args);
}
@@ -2912,7 +2912,7 @@
ASSERT(StackPointer().Is(jssp));
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
- __ Mov(temp, Operand(Smi::FromInt(StackFrame::STUB)));
+ __ Mov(temp, Smi::FromInt(StackFrame::STUB));
// Compiled stubs don't age, and so they don't need the predictable code
// ageing sequence.
__ Push(lr, fp, cp, temp);
@@ -2935,7 +2935,7 @@
Register code_reg = temps.AcquireX();
Push(lr, fp, cp);
- Mov(type_reg, Operand(Smi::FromInt(type)));
+ Mov(type_reg, Smi::FromInt(type));
Mov(code_reg, Operand(CodeObject()));
Push(type_reg, code_reg);
// jssp[4] : lr
@@ -3092,7 +3092,7 @@
Register scratch1, Register scratch2) {
if (FLAG_native_code_counters && counter->Enabled()) {
Mov(scratch1, value);
- Mov(scratch2, Operand(ExternalReference(counter)));
+ Mov(scratch2, ExternalReference(counter));
Str(scratch1, MemOperand(scratch2));
}
}
@@ -3102,7 +3102,7 @@
Register scratch1, Register scratch2) {
ASSERT(value != 0);
if (FLAG_native_code_counters && counter->Enabled()) {
- Mov(scratch2, Operand(ExternalReference(counter)));
+ Mov(scratch2, ExternalReference(counter));
Ldr(scratch1, MemOperand(scratch2));
Add(scratch1, scratch1, value);
Str(scratch1, MemOperand(scratch2));
@@ -3135,7 +3135,7 @@
#ifdef ENABLE_DEBUGGER_SUPPORT
void MacroAssembler::DebugBreak() {
Mov(x0, 0);
- Mov(x1, Operand(ExternalReference(Runtime::kDebugBreak, isolate())));
+ Mov(x1, ExternalReference(Runtime::kDebugBreak, isolate()));
CEntryStub ces(1);
ASSERT(AllowThisStubCall(&ces));
Call(ces.GetCode(isolate()), RelocInfo::DEBUG_BREAK);
@@ -3174,7 +3174,7 @@
}
// Link the current handler as the next handler.
- Mov(x11, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+ Mov(x11, ExternalReference(Isolate::kHandlerAddress, isolate()));
Ldr(x10, MemOperand(x11));
Push(x10);
// Set this new handler as the current one.
@@ -3185,7 +3185,7 @@
void MacroAssembler::PopTryHandler() {
STATIC_ASSERT(StackHandlerConstants::kNextOffset == 0);
Pop(x10);
- Mov(x11, Operand(ExternalReference(Isolate::kHandlerAddress, isolate())));
+ Mov(x11, ExternalReference(Isolate::kHandlerAddress, isolate()));
Drop(StackHandlerConstants::kSize - kXRegSize, kByteSizeInBytes);
Str(x10, MemOperand(x11));
}
@@ -3307,7 +3307,7 @@
// Set up allocation top address and object size registers.
Register top_address = scratch1;
Register allocation_limit = scratch2;
- Mov(top_address, Operand(heap_allocation_top));
+ Mov(top_address, heap_allocation_top);
if ((flags & RESULT_CONTAINS_TOP) == 0) {
// Load allocation top into result and the allocation limit.
@@ -3360,13 +3360,13 @@
Bic(object, object, kHeapObjectTagMask);
#ifdef DEBUG
// Check that the object un-allocated is below the current top.
- Mov(scratch, Operand(new_space_allocation_top));
+ Mov(scratch, new_space_allocation_top);
Ldr(scratch, MemOperand(scratch));
Cmp(object, scratch);
Check(lt, kUndoAllocationOfNonAllocatedMemory);
#endif
// Write the address of the object to un-allocate as the current top.
- Mov(scratch, Operand(new_space_allocation_top));
+ Mov(scratch, new_space_allocation_top);
Str(object, MemOperand(scratch));
}
@@ -3459,7 +3459,7 @@
ExternalReference high_promotion_mode = ExternalReference::
new_space_high_promotion_mode_active_address(isolate());
- Mov(scratch1, Operand(high_promotion_mode));
+ Mov(scratch1, high_promotion_mode);
Ldr(scratch1, MemOperand(scratch1));
Cbz(scratch1, &allocate_new_space);
@@ -4112,7 +4112,7 @@
Register scratch2 = temps.AcquireX();
// Load store buffer top.
- Mov(scratch2, Operand(ExternalReference::store_buffer_top(isolate())));
+ Mov(scratch2, ExternalReference::store_buffer_top(isolate()));
Ldr(scratch1, MemOperand(scratch2));
// Store pointer to buffer and increment buffer top.
Str(address, MemOperand(scratch1, kPointerSize, PostIndex));
@@ -4621,7 +4621,7 @@
UseScratchRegisterScope temps(this);
Register temp = temps.AcquireX();
STATIC_ASSERT(kSmiTag == 0);
- Tst(object, Operand(kSmiTagMask));
+ Tst(object, kSmiTagMask);
Check(ne, kOperandIsNotAString);
Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset));
CompareInstanceType(temp, temp, FIRST_NONSTRING_TYPE);
@@ -4676,7 +4676,7 @@
// Avoid infinite recursion; Push contains some assertions that use Abort.
NoUseRealAbortsScope no_real_aborts(this);
- Mov(x0, Operand(Smi::FromInt(reason)));
+ Mov(x0, Smi::FromInt(reason));
Push(x0);
if (!has_frame_) {
@@ -5078,7 +5078,7 @@
ASSERT(!AreAliased(result, dividend));
ASSERT(result.Is32Bits() && dividend.Is32Bits());
MultiplierAndShift ms(divisor);
- Mov(result, Operand(ms.multiplier()));
+ Mov(result, ms.multiplier());
Smull(result.X(), dividend, result);
Asr(result.X(), result.X(), 32);
if (divisor > 0 && ms.multiplier() < 0) Add(result, result, dividend);
diff --git a/src/a64/regexp-macro-assembler-a64.cc b/src/a64/regexp-macro-assembler-a64.cc
index be0a75d..0b6ade8 100644
--- a/src/a64/regexp-macro-assembler-a64.cc
+++ b/src/a64/regexp-macro-assembler-a64.cc
@@ -408,7 +408,7 @@
// Address of current input position.
__ Add(x1, input_end(), Operand(current_input_offset(), SXTW));
// Isolate.
- __ Mov(x3, Operand(ExternalReference::isolate_address(isolate())));
+ __ Mov(x3, ExternalReference::isolate_address(isolate()));
{
AllowExternalCallThatCantCauseGC scope(masm_);
@@ -634,7 +634,7 @@
CompareAndBranchOrBacktrack(current_character(), 'z', hi, on_no_match);
}
ExternalReference map = ExternalReference::re_word_character_map();
- __ Mov(x10, Operand(map));
+ __ Mov(x10, map);
__ Ldrb(w10, MemOperand(x10, current_character(), UXTW));
CompareAndBranchOrBacktrack(w10, 0, eq, on_no_match);
return true;
@@ -647,7 +647,7 @@
__ B(hi, &done);
}
ExternalReference map = ExternalReference::re_word_character_map();
- __ Mov(x10, Operand(map));
+ __ Mov(x10, map);
__ Ldrb(w10, MemOperand(x10, current_character(), UXTW));
CompareAndBranchOrBacktrack(w10, 0, ne, on_no_match);
__ Bind(&done);
@@ -736,7 +736,7 @@
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
- __ Mov(x10, Operand(stack_limit));
+ __ Mov(x10, stack_limit);
__ Ldr(x10, MemOperand(x10));
__ Subs(x10, csp, x10);
@@ -1031,7 +1031,7 @@
// The cached registers need to be retained.
__ PushCPURegList(cached_registers);
// Call GrowStack(backtrack_stackpointer(), &stack_base)
- __ Mov(x2, Operand(ExternalReference::isolate_address(isolate())));
+ __ Mov(x2, ExternalReference::isolate_address(isolate()));
__ Add(x1, frame_pointer(), kStackBase);
__ Mov(x0, backtrack_stackpointer());
ExternalReference grow_stack =
@@ -1455,7 +1455,7 @@
ExternalReference check_stack_guard_state =
ExternalReference::re_check_stack_guard_state(isolate());
- __ Mov(scratch, Operand(check_stack_guard_state));
+ __ Mov(scratch, check_stack_guard_state);
DirectCEntryStub stub;
stub.GenerateCall(masm_, scratch);
@@ -1519,7 +1519,7 @@
// Check for preemption.
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
- __ Mov(x10, Operand(stack_limit));
+ __ Mov(x10, stack_limit);
__ Ldr(x10, MemOperand(x10));
ASSERT(csp.Is(__ StackPointer()));
__ Cmp(csp, x10);
@@ -1530,7 +1530,7 @@
void RegExpMacroAssemblerA64::CheckStackLimit() {
ExternalReference stack_limit =
ExternalReference::address_of_regexp_stack_limit(isolate());
- __ Mov(x10, Operand(stack_limit));
+ __ Mov(x10, stack_limit);
__ Ldr(x10, MemOperand(x10));
__ Cmp(backtrack_stackpointer(), x10);
CallIf(&stack_overflow_label_, ls);
diff --git a/src/a64/simulator-a64.cc b/src/a64/simulator-a64.cc
index 3801bf7..d414bf5 100644
--- a/src/a64/simulator-a64.cc
+++ b/src/a64/simulator-a64.cc
@@ -51,6 +51,34 @@
#define SScanF sscanf // NOLINT
+// Helpers for colors.
+// Depending on your terminal configuration, the colour names may not match the
+// observed colours.
+#define COLOUR(colour_code) "\033[" colour_code "m"
+#define BOLD(colour_code) "1;" colour_code
+#define NORMAL ""
+#define GREY "30"
+#define GREEN "32"
+#define ORANGE "33"
+#define BLUE "34"
+#define PURPLE "35"
+#define INDIGO "36"
+#define WHITE "37"
+typedef char const * const TEXT_COLOUR;
+TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : "";
+TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR(BOLD(GREY)) : "";
+TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(BOLD(WHITE)) : "";
+TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR(BOLD(BLUE)) : "";
+TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(BOLD(INDIGO)) : "";
+TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : "";
+TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(BOLD(PURPLE)) : "";
+TEXT_COLOUR clr_memory_value = FLAG_log_colour ? COLOUR(BOLD(GREEN)) : "";
+TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR(GREEN) : "";
+TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR(BOLD(ORANGE)) : "";
+TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(ORANGE) : "";
+TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
+
+
// This is basically the same as PrintF, with a guard for FLAG_trace_sim.
void PRINTF_CHECKING TraceSim(const char* format, ...) {
if (FLAG_trace_sim) {
@@ -469,7 +497,9 @@
return reinterpret_cast<void*>(&redirect_call_);
}
- void* external_function() { return external_function_; }
+ template <typename T>
+ T external_function() { return reinterpret_cast<T>(external_function_); }
+
ExternalReference::Type type() { return type_; }
static Redirection* Get(void* external_function,
@@ -495,7 +525,7 @@
static void* ReverseRedirection(int64_t reg) {
Redirection* redirection =
FromHltInstruction(reinterpret_cast<Instruction*>(reg));
- return redirection->external_function();
+ return redirection->external_function<void*>();
}
private:
@@ -506,6 +536,223 @@
};
+// Calls into the V8 runtime are based on this very simple interface.
+// Note: To be able to return two values from some calls the code in runtime.cc
+// uses the ObjectPair structure.
+// The simulator assumes all runtime calls return two 64-bits values. If they
+// don't, register x1 is clobbered. This is fine because x1 is caller-saved.
+struct ObjectPair {
+ int64_t res0;
+ int64_t res1;
+};
+
+
+typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
+ int64_t arg1,
+ int64_t arg2,
+ int64_t arg3,
+ int64_t arg4,
+ int64_t arg5,
+ int64_t arg6,
+ int64_t arg7);
+
+typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
+typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
+typedef double (*SimulatorRuntimeFPCall)(double arg1);
+typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
+
+// This signature supports direct call in to API function native callback
+// (refer to InvocationCallback in v8.h).
+typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
+typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
+
+// This signature supports direct call to accessor getter callback.
+typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
+typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
+ void* arg2);
+
+void Simulator::DoRuntimeCall(Instruction* instr) {
+ Redirection* redirection = Redirection::FromHltInstruction(instr);
+
+ // The called C code might itself call simulated code, so any
+ // caller-saved registers (including lr) could still be clobbered by a
+ // redirected call.
+ Instruction* return_address = lr();
+
+ int64_t external = redirection->external_function<int64_t>();
+
+ TraceSim("Call to host function at %p\n",
+ redirection->external_function<void*>());
+
+ // SP must be 16-byte-aligned at the call interface.
+ bool stack_alignment_exception = ((sp() & 0xf) != 0);
+ if (stack_alignment_exception) {
+ TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
+ FATAL("ALIGNMENT EXCEPTION");
+ }
+
+ switch (redirection->type()) {
+ default:
+ TraceSim("Type: Unknown.\n");
+ UNREACHABLE();
+ break;
+
+ case ExternalReference::BUILTIN_CALL: {
+ // MaybeObject* f(v8::internal::Arguments).
+ TraceSim("Type: BUILTIN_CALL\n");
+ SimulatorRuntimeCall target =
+ reinterpret_cast<SimulatorRuntimeCall>(external);
+
+ // We don't know how many arguments are being passed, but we can
+ // pass 8 without touching the stack. They will be ignored by the
+ // host function if they aren't used.
+ TraceSim("Arguments: "
+ "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
+ "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
+ "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
+ "0x%016" PRIx64 ", 0x%016" PRIx64,
+ xreg(0), xreg(1), xreg(2), xreg(3),
+ xreg(4), xreg(5), xreg(6), xreg(7));
+ ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
+ xreg(4), xreg(5), xreg(6), xreg(7));
+ TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n",
+ result.res0, result.res1);
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ set_xreg(0, result.res0);
+ set_xreg(1, result.res1);
+ break;
+ }
+
+ case ExternalReference::DIRECT_API_CALL: {
+ // void f(v8::FunctionCallbackInfo&)
+ TraceSim("Type: DIRECT_API_CALL\n");
+ SimulatorRuntimeDirectApiCall target =
+ reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
+ TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
+ target(xreg(0));
+ TraceSim("No return value.");
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ break;
+ }
+
+ case ExternalReference::BUILTIN_COMPARE_CALL: {
+ // int f(double, double)
+ TraceSim("Type: BUILTIN_COMPARE_CALL\n");
+ SimulatorRuntimeCompareCall target =
+ reinterpret_cast<SimulatorRuntimeCompareCall>(external);
+ TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
+ int64_t result = target(dreg(0), dreg(1));
+ TraceSim("Returned: %" PRId64 "\n", result);
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ set_xreg(0, result);
+ break;
+ }
+
+ case ExternalReference::BUILTIN_FP_CALL: {
+ // double f(double)
+ TraceSim("Type: BUILTIN_FP_CALL\n");
+ SimulatorRuntimeFPCall target =
+ reinterpret_cast<SimulatorRuntimeFPCall>(external);
+ TraceSim("Argument: %f\n", dreg(0));
+ double result = target(dreg(0));
+ TraceSim("Returned: %f\n", result);
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ set_dreg(0, result);
+ break;
+ }
+
+ case ExternalReference::BUILTIN_FP_FP_CALL: {
+ // double f(double, double)
+ TraceSim("Type: BUILTIN_FP_FP_CALL\n");
+ SimulatorRuntimeFPFPCall target =
+ reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
+ TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
+ double result = target(dreg(0), dreg(1));
+ TraceSim("Returned: %f\n", result);
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ set_dreg(0, result);
+ break;
+ }
+
+ case ExternalReference::BUILTIN_FP_INT_CALL: {
+ // double f(double, int)
+ TraceSim("Type: BUILTIN_FP_INT_CALL\n");
+ SimulatorRuntimeFPIntCall target =
+ reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
+ TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
+ double result = target(dreg(0), wreg(0));
+ TraceSim("Returned: %f\n", result);
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ set_dreg(0, result);
+ break;
+ }
+
+ case ExternalReference::DIRECT_GETTER_CALL: {
+ // void f(Local<String> property, PropertyCallbackInfo& info)
+ TraceSim("Type: DIRECT_GETTER_CALL\n");
+ SimulatorRuntimeDirectGetterCall target =
+ reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
+ TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
+ xreg(0), xreg(1));
+ target(xreg(0), xreg(1));
+ TraceSim("No return value.");
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ break;
+ }
+
+ case ExternalReference::PROFILING_API_CALL: {
+ // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
+ TraceSim("Type: PROFILING_API_CALL\n");
+ SimulatorRuntimeProfilingApiCall target =
+ reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
+ void* arg1 = Redirection::ReverseRedirection(xreg(1));
+ TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
+ target(xreg(0), arg1);
+ TraceSim("No return value.");
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ break;
+ }
+
+ case ExternalReference::PROFILING_GETTER_CALL: {
+ // void f(Local<String> property, PropertyCallbackInfo& info,
+ // AccessorGetterCallback callback)
+ TraceSim("Type: PROFILING_GETTER_CALL\n");
+ SimulatorRuntimeProfilingGetterCall target =
+ reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
+ external);
+ void* arg2 = Redirection::ReverseRedirection(xreg(2));
+ TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
+ xreg(0), xreg(1), arg2);
+ target(xreg(0), xreg(1), arg2);
+ TraceSim("No return value.");
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+ break;
+ }
+ }
+
+ set_lr(return_address);
+ set_pc(return_address);
+}
+
+
void* Simulator::RedirectExternalReference(void* external_function,
ExternalReference::Type type) {
Redirection* redirection = Redirection::Get(external_function, type);
@@ -820,12 +1067,6 @@
void Simulator::PrintSystemRegisters(bool print_all) {
static bool first_run = true;
- // Define some colour codes to use for the register dump.
- // TODO(jbramley): Find a more elegant way of defining these.
- char const * const clr_normal = (FLAG_log_colour) ? ("\033[m") : ("");
- char const * const clr_flag_name = (FLAG_log_colour) ? ("\033[1;30m") : ("");
- char const * const clr_flag_value = (FLAG_log_colour) ? ("\033[1;37m") : ("");
-
static SimSystemRegister last_nzcv;
if (print_all || first_run || (last_nzcv.RawValue() != nzcv().RawValue())) {
fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
@@ -861,12 +1102,6 @@
static bool first_run = true;
static int64_t last_regs[kNumberOfRegisters];
- // Define some colour codes to use for the register dump.
- // TODO(jbramley): Find a more elegant way of defining these.
- char const * const clr_normal = (FLAG_log_colour) ? ("\033[m") : ("");
- char const * const clr_reg_name = (FLAG_log_colour) ? ("\033[1;34m") : ("");
- char const * const clr_reg_value = (FLAG_log_colour) ? ("\033[1;36m") : ("");
-
for (unsigned i = 0; i < kNumberOfRegisters; i++) {
if (print_all_regs || first_run ||
(last_regs[i] != xreg(i, Reg31IsStackPointer))) {
@@ -889,12 +1124,6 @@
static bool first_run = true;
static uint64_t last_regs[kNumberOfFPRegisters];
- // Define some colour codes to use for the register dump.
- // TODO(jbramley): Find a more elegant way of defining these.
- char const * const clr_normal = (FLAG_log_colour) ? ("\033[m") : ("");
- char const * const clr_reg_name = (FLAG_log_colour) ? ("\033[1;33m") : ("");
- char const * const clr_reg_value = (FLAG_log_colour) ? ("\033[1;35m") : ("");
-
// Print as many rows of registers as necessary, keeping each individual
// register in the same column each time (to make it easy to visually scan
// for changes).
@@ -902,18 +1131,18 @@
if (print_all_regs || first_run || (last_regs[i] != dreg_bits(i))) {
fprintf(stream_,
"# %s %4s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
- clr_reg_name,
+ clr_fpreg_name,
VRegNameForCode(i),
- clr_reg_value,
+ clr_fpreg_value,
dreg_bits(i),
clr_normal,
- clr_reg_name,
+ clr_fpreg_name,
DRegNameForCode(i),
- clr_reg_value,
+ clr_fpreg_value,
dreg(i),
- clr_reg_name,
+ clr_fpreg_name,
SRegNameForCode(i),
- clr_reg_value,
+ clr_fpreg_value,
sreg(i),
clr_normal);
}
@@ -2949,14 +3178,6 @@
bool Simulator::PrintValue(const char* desc) {
- // Define some colour codes to use for the register dump.
- // TODO(jbramley): Find a more elegant way of defining these.
- char const * const clr_normal = FLAG_log_colour ? "\033[m" : "";
- char const * const clr_reg_name = FLAG_log_colour ? "\033[1;34m" : "";
- char const * const clr_reg_value = FLAG_log_colour ? "\033[1;36m" : "";
- char const * const clr_fpreg_name = FLAG_log_colour ? "\033[1;33m" : "";
- char const * const clr_fpreg_value = FLAG_log_colour ? "\033[1;35m" : "";
-
if (strcmp(desc, "csp") == 0) {
ASSERT(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
PrintF("%s csp:%s 0x%016" PRIx64 "%s\n",
@@ -3299,53 +3520,7 @@
}
-// Calls into the V8 runtime are based on this very simple interface.
-// Note: To be able to return two values from some calls the code in runtime.cc
-// uses the ObjectPair structure.
-// The simulator assumes all runtime calls return two 64-bits values. If they
-// don't, register x1 is clobbered. This is fine because x1 is caller-saved.
-struct ObjectPair {
- int64_t res0;
- int64_t res1;
-};
-
-
-typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0,
- int64_t arg1,
- int64_t arg2,
- int64_t arg3,
- int64_t arg4,
- int64_t arg5,
- int64_t arg6,
- int64_t arg7);
-
-typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2);
-typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2);
-typedef double (*SimulatorRuntimeFPCall)(double arg1);
-typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2);
-
-// This signature supports direct call in to API function native callback
-// (refer to InvocationCallback in v8.h).
-typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0);
-typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1);
-
-// This signature supports direct call to accessor getter callback.
-typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1);
-typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1,
- void* arg2);
-
void Simulator::VisitException(Instruction* instr) {
- // Define some colour codes to use for log messages.
- // TODO(jbramley): Find a more elegant way of defining these.
- char const* const clr_normal = (FLAG_log_colour) ? ("\033[m")
- : ("");
- char const* const clr_debug_number = (FLAG_log_colour) ? ("\033[1;33m")
- : ("");
- char const* const clr_debug_message = (FLAG_log_colour) ? ("\033[0;33m")
- : ("");
- char const* const clr_printf = (FLAG_log_colour) ? ("\033[0;32m")
- : ("");
-
switch (instr->Mask(ExceptionMask)) {
case HLT: {
if (instr->ImmException() == kImmExceptionIsDebug) {
@@ -3421,190 +3596,7 @@
if (parameters & BREAK) Debug();
} else if (instr->ImmException() == kImmExceptionIsRedirectedCall) {
- // TODO(all): Extract the call redirection code into a separate
- // function.
-
- Redirection* redirection = Redirection::FromHltInstruction(instr);
-
- // The called C code might itself call simulated code, so any
- // caller-saved registers (including lr) could still be clobbered by a
- // redirected call.
- Instruction* return_address = lr();
-
- // TODO(jbramley): Make external_function() a template so that we don't
- // have to explicitly cast the result for each redirection type.
- int64_t external =
- reinterpret_cast<int64_t>(redirection->external_function());
-
- TraceSim("Call to host function at %p\n",
- reinterpret_cast<void*>(redirection->external_function()));
-
- // SP must be 16 bytes aligned at the call interface.
- bool stack_alignment_exception = ((sp() & 0xf) != 0);
- if (stack_alignment_exception) {
- TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp());
- FATAL("ALIGNMENT EXCEPTION");
- }
-
- switch (redirection->type()) {
- default:
- TraceSim("Type: Unknown.\n");
- UNREACHABLE();
- break;
-
- case ExternalReference::BUILTIN_CALL: {
- // MaybeObject* f(v8::internal::Arguments).
- TraceSim("Type: BUILTIN_CALL\n");
- SimulatorRuntimeCall target =
- reinterpret_cast<SimulatorRuntimeCall>(external);
-
- // We don't know how many arguments are being passed, but we can
- // pass 8 without touching the stack. They will be ignored by the
- // host function if they aren't used.
- TraceSim("Arguments: "
- "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
- "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
- "0x%016" PRIx64 ", 0x%016" PRIx64 ", "
- "0x%016" PRIx64 ", 0x%016" PRIx64,
- xreg(0), xreg(1), xreg(2), xreg(3),
- xreg(4), xreg(5), xreg(6), xreg(7));
- ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3),
- xreg(4), xreg(5), xreg(6), xreg(7));
- TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64"}\n",
- result.res0, result.res1);
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- set_xreg(0, result.res0);
- set_xreg(1, result.res1);
- break;
- }
-
- case ExternalReference::DIRECT_API_CALL: {
- // void f(v8::FunctionCallbackInfo&)
- TraceSim("Type: DIRECT_API_CALL\n");
- SimulatorRuntimeDirectApiCall target =
- reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
- TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0));
- target(xreg(0));
- TraceSim("No return value.");
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- break;
- }
-
- case ExternalReference::BUILTIN_COMPARE_CALL: {
- // int f(double, double)
- TraceSim("Type: BUILTIN_COMPARE_CALL\n");
- SimulatorRuntimeCompareCall target =
- reinterpret_cast<SimulatorRuntimeCompareCall>(external);
- TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
- int64_t result = target(dreg(0), dreg(1));
- TraceSim("Returned: %" PRId64 "\n", result);
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- set_xreg(0, result);
- break;
- }
-
- case ExternalReference::BUILTIN_FP_CALL: {
- // double f(double)
- TraceSim("Type: BUILTIN_FP_CALL\n");
- SimulatorRuntimeFPCall target =
- reinterpret_cast<SimulatorRuntimeFPCall>(external);
- TraceSim("Argument: %f\n", dreg(0));
- double result = target(dreg(0));
- TraceSim("Returned: %f\n", result);
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- set_dreg(0, result);
- break;
- }
-
- case ExternalReference::BUILTIN_FP_FP_CALL: {
- // double f(double, double)
- TraceSim("Type: BUILTIN_FP_FP_CALL\n");
- SimulatorRuntimeFPFPCall target =
- reinterpret_cast<SimulatorRuntimeFPFPCall>(external);
- TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1));
- double result = target(dreg(0), dreg(1));
- TraceSim("Returned: %f\n", result);
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- set_dreg(0, result);
- break;
- }
-
- case ExternalReference::BUILTIN_FP_INT_CALL: {
- // double f(double, int)
- TraceSim("Type: BUILTIN_FP_INT_CALL\n");
- SimulatorRuntimeFPIntCall target =
- reinterpret_cast<SimulatorRuntimeFPIntCall>(external);
- TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0));
- double result = target(dreg(0), wreg(0));
- TraceSim("Returned: %f\n", result);
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- set_dreg(0, result);
- break;
- }
-
- case ExternalReference::DIRECT_GETTER_CALL: {
- // void f(Local<String> property, PropertyCallbackInfo& info)
- TraceSim("Type: DIRECT_GETTER_CALL\n");
- SimulatorRuntimeDirectGetterCall target =
- reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
- TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n",
- xreg(0), xreg(1));
- target(xreg(0), xreg(1));
- TraceSim("No return value.");
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- break;
- }
-
- case ExternalReference::PROFILING_API_CALL: {
- // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
- TraceSim("Type: PROFILING_API_CALL\n");
- SimulatorRuntimeProfilingApiCall target =
- reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
- void* arg1 = Redirection::ReverseRedirection(xreg(1));
- TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1);
- target(xreg(0), arg1);
- TraceSim("No return value.");
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- break;
- }
-
- case ExternalReference::PROFILING_GETTER_CALL: {
- // void f(Local<String> property, PropertyCallbackInfo& info,
- // AccessorGetterCallback callback)
- TraceSim("Type: PROFILING_GETTER_CALL\n");
- SimulatorRuntimeProfilingGetterCall target =
- reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(
- external);
- void* arg2 = Redirection::ReverseRedirection(xreg(2));
- TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n",
- xreg(0), xreg(1), arg2);
- target(xreg(0), xreg(1), arg2);
- TraceSim("No return value.");
-#ifdef DEBUG
- CorruptAllCallerSavedCPURegisters();
-#endif
- break;
- }
- }
-
- set_lr(return_address);
- set_pc(return_address);
+ DoRuntimeCall(instr);
} else if (instr->ImmException() == kImmExceptionIsPrintf) {
// Read the argument encoded inline in the instruction stream.
uint32_t type;
@@ -3631,9 +3623,12 @@
result = fprintf(stream_, "%s", format);
}
fputs(clr_normal, stream_);
- set_xreg(0, result);
- // TODO(jbramley): Consider clobbering all caller-saved registers here.
+#ifdef DEBUG
+ CorruptAllCallerSavedCPURegisters();
+#endif
+
+ set_xreg(0, result);
// The printf parameters are inlined in the code, so skip them.
set_pc(pc_->InstructionAtOffset(kPrintfLength));
diff --git a/src/a64/simulator-a64.h b/src/a64/simulator-a64.h
index 959644b..0d973e8 100644
--- a/src/a64/simulator-a64.h
+++ b/src/a64/simulator-a64.h
@@ -311,6 +311,7 @@
// Runtime call support.
static void* RedirectExternalReference(void* external_function,
ExternalReference::Type type);
+ void DoRuntimeCall(Instruction* instr);
// Run the simulator.
static const Instruction* kEndOfSimAddress;
diff --git a/src/a64/stub-cache-a64.cc b/src/a64/stub-cache-a64.cc
index 291da65..1e59c0e 100644
--- a/src/a64/stub-cache-a64.cc
+++ b/src/a64/stub-cache-a64.cc
@@ -125,7 +125,7 @@
__ Add(scratch3, offset, Operand(offset, LSL, 1));
// Calculate the base address of the entry.
- __ Mov(scratch, Operand(key_offset));
+ __ Mov(scratch, key_offset);
__ Add(scratch, scratch, Operand(scratch3, LSL, kPointerSizeLog2));
// Check that the key in the entry matches the name.
@@ -461,16 +461,11 @@
// TODO(verwaest): Share this code as a code stub.
SmiCheck smi_check = representation.IsTagged()
? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
+ Register prop_reg = representation.IsDouble() ? storage_reg : value_reg;
if (index < 0) {
// Set the property straight into the object.
int offset = object->map()->instance_size() + (index * kPointerSize);
- // TODO(jbramley): This construct appears in several places in this
- // function. Try to clean it up, perhaps using a result_reg.
- if (representation.IsDouble()) {
- __ Str(storage_reg, FieldMemOperand(receiver_reg, offset));
- } else {
- __ Str(value_reg, FieldMemOperand(receiver_reg, offset));
- }
+ __ Str(prop_reg, FieldMemOperand(receiver_reg, offset));
if (!representation.IsSmi()) {
// Update the write barrier for the array address.
@@ -492,11 +487,7 @@
// Get the properties array
__ Ldr(scratch1,
FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
- if (representation.IsDouble()) {
- __ Str(storage_reg, FieldMemOperand(scratch1, offset));
- } else {
- __ Str(value_reg, FieldMemOperand(scratch1, offset));
- }
+ __ Str(prop_reg, FieldMemOperand(scratch1, offset));
if (!representation.IsSmi()) {
// Update the write barrier for the array address.
@@ -761,7 +752,7 @@
ExternalReference ref = ExternalReference(&fun,
ExternalReference::DIRECT_API_CALL,
masm->isolate());
- __ Mov(api_function_address, Operand(ref));
+ __ Mov(api_function_address, ref);
// Jump to stub.
CallApiFunctionStub stub(is_store, call_data_undefined, argc);
@@ -1022,7 +1013,7 @@
// together. Can we use scratch1() here?
__ LoadRoot(scratch4(), Heap::kUndefinedValueRootIndex);
__ Push(scratch3(), scratch4());
- __ Mov(scratch3(), Operand(ExternalReference::isolate_address(isolate())));
+ __ Mov(scratch3(), ExternalReference::isolate_address(isolate()));
__ Push(scratch4(), scratch3(), reg, name());
Register args_addr = scratch2();
@@ -1044,7 +1035,7 @@
ApiFunction fun(getter_address);
ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
ExternalReference ref = ExternalReference(&fun, type, isolate());
- __ Mov(getter_address_reg, Operand(ref));
+ __ Mov(getter_address_reg, ref);
CallApiGetterStub stub;
__ TailCallStub(&stub);
diff --git a/src/api.cc b/src/api.cc
index d0c9d26..402598f 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2203,9 +2203,10 @@
ENTER_V8(isolate);
EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
i::Handle<i::JSArray> self = Utils::OpenHandle(this);
- i::Object* raw_object = self->GetElementNoExceptionThrown(isolate, index);
- i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
- return scope.Escape(Utils::StackFrameToLocal(obj));
+ i::Handle<i::Object> obj =
+ i::Object::GetElementNoExceptionThrown(isolate, self, index);
+ i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
+ return scope.Escape(Utils::StackFrameToLocal(jsobj));
}
@@ -5475,6 +5476,8 @@
i::Handle<i::String> right_string = Utils::OpenHandle(*right);
i::Handle<i::String> result = isolate->factory()->NewConsString(left_string,
right_string);
+ // We do not expect this to throw an exception. Change this if it does.
+ CHECK_NOT_EMPTY_HANDLE(isolate, result);
return Utils::ToLocal(result);
}
@@ -6966,9 +6969,12 @@
return ToApiHandle<String>(
isolate->factory()->InternalizeUtf8String(entry->name()));
} else {
- return ToApiHandle<String>(isolate->factory()->NewConsString(
+ i::Handle<i::String> cons = isolate->factory()->NewConsString(
isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
- isolate->factory()->InternalizeUtf8String(entry->name())));
+ isolate->factory()->InternalizeUtf8String(entry->name()));
+ // We do not expect this to throw an exception. Change this if it does.
+ CHECK_NOT_EMPTY_HANDLE(isolate, cons);
+ return ToApiHandle<String>(cons);
}
}
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index fac89e4..55705b8 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -1332,20 +1332,25 @@
ASSERT(instr->right()->representation().Equals(instr->representation()));
LOperand* dividend = UseRegister(instr->left());
int32_t divisor = instr->right()->GetInteger32Constant();
- LInstruction* result =
- DefineAsRegister(new(zone()) LFlooringDivByConstI(dividend, divisor));
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
- return can_deopt ? AssignEnvironment(result) : result;
+ LOperand* temp =
+ ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
+ NULL : TempRegister();
+ LInstruction* result = DefineAsRegister(
+ new(zone()) LFlooringDivByConstI(dividend, divisor, temp));
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
if (instr->RightIsPowerOf2()) {
return DoFlooringDivByPowerOf2I(instr);
- } else if (false && instr->right()->IsConstant()) {
- return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable.
+ } else if (instr->right()->IsConstant()) {
+ return DoFlooringDivByConstI(instr);
} else {
return DoDivI(instr);
}
diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
index 631efc7..34eb510 100644
--- a/src/arm/lithium-arm.h
+++ b/src/arm/lithium-arm.h
@@ -747,16 +747,17 @@
};
-class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 0> {
+class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
public:
- LFlooringDivByConstI(LOperand* dividend, int32_t divisor) {
+ LFlooringDivByConstI(LOperand* dividend, int32_t divisor, LOperand* temp) {
inputs_[0] = dividend;
divisor_ = divisor;
+ temps_[0] = temp;
}
LOperand* dividend() { return inputs_[0]; }
int32_t divisor() const { return divisor_; }
- LOperand* temp1() { return temps_[0]; }
+ LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 33ac25f..dc31547 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -1507,8 +1507,31 @@
DeoptimizeIf(eq, instr->environment());
}
- // TODO(svenpanne) Add correction terms.
- __ TruncatingDiv(result, dividend, divisor);
+ // Easy case: We need no dynamic check for the dividend and the flooring
+ // division is the same as the truncating division.
+ if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
+ __ TruncatingDiv(result, dividend, Abs(divisor));
+ if (divisor < 0) __ rsb(result, result, Operand::Zero());
+ return;
+ }
+
+ // In the general case we may need to adjust before and after the truncating
+ // division to get a flooring division.
+ Register temp = ToRegister(instr->temp());
+ ASSERT(!temp.is(dividend) && !temp.is(result));
+ Label needs_adjustment, done;
+ __ cmp(dividend, Operand::Zero());
+ __ b(divisor > 0 ? lt : gt, &needs_adjustment);
+ __ TruncatingDiv(result, dividend, Abs(divisor));
+ if (divisor < 0) __ rsb(result, result, Operand::Zero());
+ __ jmp(&done);
+ __ bind(&needs_adjustment);
+ __ add(temp, dividend, Operand(divisor > 0 ? 1 : -1));
+ __ TruncatingDiv(result, temp, Abs(divisor));
+ if (divisor < 0) __ rsb(result, result, Operand::Zero());
+ __ sub(result, result, Operand(1));
+ __ bind(&done);
}
diff --git a/src/builtins.cc b/src/builtins.cc
index b48de7f..be9051c 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -367,6 +367,7 @@
}
+// TODO(ishell): Handlify when all Array* builtins are handlified.
static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap,
JSArray* receiver) {
if (!FLAG_clever_optimizations) return false;
@@ -406,23 +407,21 @@
BUILTIN(ArrayPush) {
- Heap* heap = isolate->heap();
- Object* receiver = *args.receiver();
- FixedArrayBase* elms_obj;
- MaybeObject* maybe_elms_obj =
- EnsureJSArrayWithWritableFastElements(heap, receiver, &args, 1);
- if (maybe_elms_obj == NULL) {
- return CallJsBuiltin(isolate, "ArrayPush", args);
- }
- if (!maybe_elms_obj->To(&elms_obj)) return maybe_elms_obj;
+ HandleScope scope(isolate);
+ Handle<Object> receiver = args.receiver();
+ Handle<Object> elms_or_null =
+ EnsureJSArrayWithWritableFastElementsWrapper(isolate, receiver, &args, 1);
+ RETURN_IF_EMPTY_HANDLE(isolate, elms_or_null);
+ if (*elms_or_null == NULL) return CallJsBuiltin(isolate, "ArrayPush", args);
- JSArray* array = JSArray::cast(receiver);
+ Handle<FixedArrayBase> elms_obj = Handle<FixedArrayBase>::cast(elms_or_null);
+ Handle<JSArray> array = Handle<JSArray>::cast(receiver);
ASSERT(!array->map()->is_observed());
ElementsKind kind = array->GetElementsKind();
if (IsFastSmiOrObjectElementsKind(kind)) {
- FixedArray* elms = FixedArray::cast(elms_obj);
+ Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
int len = Smi::cast(array->length())->value();
int to_add = args.length() - 1;
@@ -438,16 +437,13 @@
if (new_length > elms->length()) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
- FixedArray* new_elms;
- MaybeObject* maybe_obj = heap->AllocateUninitializedFixedArray(capacity);
- if (!maybe_obj->To(&new_elms)) return maybe_obj;
+ Handle<FixedArray> new_elms =
+ isolate->factory()->NewUninitializedFixedArray(capacity);
ElementsAccessor* accessor = array->GetElementsAccessor();
- MaybeObject* maybe_failure = accessor->CopyElements(
- NULL, 0, kind, new_elms, 0,
- ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
- ASSERT(!maybe_failure->IsFailure());
- USE(maybe_failure);
+ accessor->CopyElements(
+ Handle<JSObject>::null(), 0, kind, new_elms, 0,
+ ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
elms = new_elms;
}
@@ -459,8 +455,8 @@
elms->set(index + len, args[index + 1], mode);
}
- if (elms != array->elements()) {
- array->set_elements(elms);
+ if (*elms != array->elements()) {
+ array->set_elements(*elms);
}
// Set the length.
@@ -480,25 +476,22 @@
int new_length = len + to_add;
- FixedDoubleArray* new_elms;
+ Handle<FixedDoubleArray> new_elms;
if (new_length > elms_len) {
// New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16;
- MaybeObject* maybe_obj =
- heap->AllocateUninitializedFixedDoubleArray(capacity);
- if (!maybe_obj->To(&new_elms)) return maybe_obj;
+ new_elms = isolate->factory()->NewFixedDoubleArray(capacity);
ElementsAccessor* accessor = array->GetElementsAccessor();
- MaybeObject* maybe_failure = accessor->CopyElements(
- NULL, 0, kind, new_elms, 0,
- ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
- ASSERT(!maybe_failure->IsFailure());
- USE(maybe_failure);
+ accessor->CopyElements(
+ Handle<JSObject>::null(), 0, kind, new_elms, 0,
+ ElementsAccessor::kCopyToEndAndInitializeToHole, elms_obj);
+
} else {
// to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the
// empty_fixed_array.
- new_elms = FixedDoubleArray::cast(elms_obj);
+ new_elms = Handle<FixedDoubleArray>::cast(elms_obj);
}
// Add the provided values.
@@ -509,8 +502,8 @@
new_elms->set(index + len, arg->Number());
}
- if (new_elms != array->elements()) {
- array->set_elements(new_elms);
+ if (*new_elms != array->elements()) {
+ array->set_elements(*new_elms);
}
// Set the length.
@@ -583,19 +576,19 @@
BUILTIN(ArrayShift) {
+ HandleScope scope(isolate);
Heap* heap = isolate->heap();
- Object* receiver = *args.receiver();
- FixedArrayBase* elms_obj;
- MaybeObject* maybe_elms_obj =
- EnsureJSArrayWithWritableFastElements(heap, receiver, NULL, 0);
- if (maybe_elms_obj == NULL)
- return CallJsBuiltin(isolate, "ArrayShift", args);
- if (!maybe_elms_obj->To(&elms_obj)) return maybe_elms_obj;
-
- if (!IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(receiver))) {
+ Handle<Object> receiver = args.receiver();
+ Handle<Object> elms_or_null =
+ EnsureJSArrayWithWritableFastElementsWrapper(isolate, receiver, NULL, 0);
+ RETURN_IF_EMPTY_HANDLE(isolate, elms_or_null);
+ if ((*elms_or_null == NULL) ||
+ !IsJSArrayFastElementMovingAllowed(heap,
+ *Handle<JSArray>::cast(receiver))) {
return CallJsBuiltin(isolate, "ArrayShift", args);
}
- JSArray* array = JSArray::cast(receiver);
+ Handle<FixedArrayBase> elms_obj = Handle<FixedArrayBase>::cast(elms_or_null);
+ Handle<JSArray> array = Handle<JSArray>::cast(receiver);
ASSERT(!array->map()->is_observed());
int len = Smi::cast(array->length())->value();
@@ -603,25 +596,23 @@
// Get first element
ElementsAccessor* accessor = array->GetElementsAccessor();
- Object* first;
- MaybeObject* maybe_first = accessor->Get(receiver, array, 0, elms_obj);
- if (!maybe_first->To(&first)) return maybe_first;
+ Handle<Object> first = accessor->Get(receiver, array, 0, elms_obj);
if (first->IsTheHole()) {
- first = heap->undefined_value();
+ first = isolate->factory()->undefined_value();
}
- if (!heap->lo_space()->Contains(elms_obj)) {
- array->set_elements(LeftTrimFixedArray(heap, elms_obj, 1));
+ if (!heap->lo_space()->Contains(*elms_obj)) {
+ array->set_elements(LeftTrimFixedArray(heap, *elms_obj, 1));
} else {
// Shift the elements.
if (elms_obj->IsFixedArray()) {
- FixedArray* elms = FixedArray::cast(elms_obj);
+ Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
DisallowHeapAllocation no_gc;
- heap->MoveElements(elms, 0, 1, len - 1);
+ heap->MoveElements(*elms, 0, 1, len - 1);
elms->set(len - 1, heap->the_hole_value());
} else {
- FixedDoubleArray* elms = FixedDoubleArray::cast(elms_obj);
- MoveDoubleElements(elms, 0, elms, 1, len - 1);
+ Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
+ MoveDoubleElements(*elms, 0, *elms, 1, len - 1);
elms->set_the_hole(len - 1);
}
}
@@ -629,7 +620,7 @@
// Set the length.
array->set_length(Smi::FromInt(len - 1));
- return first;
+ return *first;
}
diff --git a/src/elements.cc b/src/elements.cc
index d935fb1..5d3ef13 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -639,6 +639,19 @@
receiver, holder, key, backing_store);
}
+ // TODO(ishell): Temporary wrapper until handlified.
+ MUST_USE_RESULT virtual Handle<Object> Get(
+ Handle<Object> receiver,
+ Handle<JSObject> holder,
+ uint32_t key,
+ Handle<FixedArrayBase> backing_store) {
+ CALL_HEAP_FUNCTION(holder->GetIsolate(),
+ Get(*receiver, *holder, key,
+ backing_store.is_null()
+ ? NULL : *backing_store),
+ Object);
+ }
+
MUST_USE_RESULT virtual MaybeObject* Get(Object* receiver,
JSObject* holder,
uint32_t key,
@@ -768,9 +781,10 @@
return obj;
}
- MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
- uint32_t key,
- JSReceiver::DeleteMode mode) = 0;
+ MUST_USE_RESULT virtual Handle<Object> Delete(
+ Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) = 0;
MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start,
@@ -783,6 +797,21 @@
return NULL;
}
+ virtual void CopyElements(
+ Handle<JSObject> from_holder,
+ uint32_t from_start,
+ ElementsKind from_kind,
+ Handle<FixedArrayBase> to,
+ uint32_t to_start,
+ int copy_size,
+ Handle<FixedArrayBase> from) {
+ CALL_HEAP_FUNCTION_VOID(from_holder->GetIsolate(),
+ CopyElements(
+ from_holder.is_null() ? NULL : *from_holder,
+ from_start, from_kind, *to, to_start, copy_size,
+ from.is_null() ? NULL : *from));
+ }
+
MUST_USE_RESULT virtual MaybeObject* CopyElements(JSObject* from_holder,
uint32_t from_start,
ElementsKind from_kind,
@@ -999,42 +1028,38 @@
Object);
}
- static MaybeObject* DeleteCommon(JSObject* obj,
- uint32_t key,
- JSReceiver::DeleteMode mode) {
+ static Handle<Object> DeleteCommon(Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) {
ASSERT(obj->HasFastSmiOrObjectElements() ||
obj->HasFastDoubleElements() ||
obj->HasFastArgumentsElements());
+ Isolate* isolate = obj->GetIsolate();
Heap* heap = obj->GetHeap();
- Object* elements = obj->elements();
- if (elements == heap->empty_fixed_array()) {
- return heap->true_value();
+ Handle<Object> elements = handle(obj->elements(), isolate);
+ if (*elements == heap->empty_fixed_array()) {
+ return isolate->factory()->true_value();
}
- typename KindTraits::BackingStore* backing_store =
- KindTraits::BackingStore::cast(elements);
+ Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
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));
+ backing_store = Handle<BackingStore>::cast(
+ handle(Handle<FixedArray>::cast(backing_store)->get(1), isolate));
}
uint32_t length = static_cast<uint32_t>(
obj->IsJSArray()
- ? Smi::cast(JSArray::cast(obj)->length())->value()
+ ? Smi::cast(Handle<JSArray>::cast(obj)->length())->value()
: backing_store->length());
if (key < length) {
if (!is_sloppy_arguments_elements_map) {
ElementsKind kind = KindTraits::Kind;
if (IsFastPackedElementsKind(kind)) {
- MaybeObject* transitioned =
- obj->TransitionElementsKind(GetHoleyElementsKind(kind));
- if (transitioned->IsFailure()) return transitioned;
+ JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
}
if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
- Object* writable;
- MaybeObject* maybe = obj->EnsureWritableFastElements();
- if (!maybe->ToObject(&writable)) return maybe;
- backing_store = KindTraits::BackingStore::cast(writable);
+ Handle<Object> writable = JSObject::EnsureWritableFastElements(obj);
+ backing_store = Handle<BackingStore>::cast(writable);
}
}
backing_store->set_the_hole(key);
@@ -1044,7 +1069,7 @@
// one adjacent hole to the value being deleted.
const int kMinLengthForSparsenessCheck = 64;
if (backing_store->length() >= kMinLengthForSparsenessCheck &&
- !heap->InNewSpace(backing_store) &&
+ !heap->InNewSpace(*backing_store) &&
((key > 0 && backing_store->is_the_hole(key - 1)) ||
(key + 1 < length && backing_store->is_the_hole(key + 1)))) {
int num_used = 0;
@@ -1054,17 +1079,16 @@
if (4 * num_used > backing_store->length()) break;
}
if (4 * num_used <= backing_store->length()) {
- MaybeObject* result = obj->NormalizeElements();
- if (result->IsFailure()) return result;
+ JSObject::NormalizeElements(obj);
}
}
}
- return heap->true_value();
+ return isolate->factory()->true_value();
}
- virtual MaybeObject* Delete(JSObject* obj,
- uint32_t key,
- JSReceiver::DeleteMode mode) {
+ virtual Handle<Object> Delete(Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) {
return DeleteCommon(obj, key, mode);
}
@@ -1396,11 +1420,11 @@
return obj;
}
- MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
- uint32_t key,
- JSReceiver::DeleteMode mode) {
+ MUST_USE_RESULT virtual Handle<Object> Delete(Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) {
// External arrays always ignore deletes.
- return obj->GetHeap()->true_value();
+ return obj->GetIsolate()->factory()->true_value();
}
static bool HasElementImpl(Object* receiver,
@@ -1555,6 +1579,16 @@
return heap->true_value();
}
+ // TODO(ishell): Temporary wrapper until handlified.
+ MUST_USE_RESULT static Handle<Object> DeleteCommon(
+ Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) {
+ CALL_HEAP_FUNCTION(obj->GetIsolate(),
+ DeleteCommon(*obj, key, mode),
+ Object);
+ }
+
MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
uint32_t from_start,
FixedArrayBase* to,
@@ -1571,9 +1605,9 @@
friend class ElementsAccessorBase<DictionaryElementsAccessor,
ElementsKindTraits<DICTIONARY_ELEMENTS> >;
- MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
- uint32_t key,
- JSReceiver::DeleteMode mode) {
+ MUST_USE_RESULT virtual Handle<Object> Delete(Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) {
return DeleteCommon(obj, key, mode);
}
@@ -1763,18 +1797,21 @@
return obj;
}
- MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* obj,
- uint32_t key,
- JSReceiver::DeleteMode mode) {
- FixedArray* parameter_map = FixedArray::cast(obj->elements());
- Object* probe = GetParameterMapArg(obj, parameter_map, key);
+ MUST_USE_RESULT virtual Handle<Object> Delete(Handle<JSObject> obj,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) {
+ Isolate* isolate = obj->GetIsolate();
+ Handle<FixedArray> parameter_map =
+ handle(FixedArray::cast(obj->elements()), isolate);
+ Handle<Object> probe = GetParameterMapArg(obj, parameter_map, key);
if (!probe->IsTheHole()) {
// TODO(kmillikin): We could check if this was the last aliased
// parameter, and revert to normal elements in that case. That
// would enable GC of the context.
parameter_map->set_the_hole(key + 2);
} else {
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
+ Handle<FixedArray> arguments =
+ handle(FixedArray::cast(parameter_map->get(1)), isolate);
if (arguments->IsDictionary()) {
return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
} else {
@@ -1784,7 +1821,7 @@
return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode);
}
}
- return obj->GetHeap()->true_value();
+ return isolate->factory()->true_value();
}
MUST_USE_RESULT static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
@@ -1827,6 +1864,7 @@
}
private:
+ // TODO(ishell): remove when all usages are handlified.
static Object* GetParameterMapArg(JSObject* holder,
FixedArray* parameter_map,
uint32_t key) {
@@ -1837,6 +1875,18 @@
? parameter_map->get(key + 2)
: parameter_map->GetHeap()->the_hole_value();
}
+
+ static Handle<Object> GetParameterMapArg(Handle<JSObject> holder,
+ Handle<FixedArray> parameter_map,
+ uint32_t key) {
+ Isolate* isolate = holder->GetIsolate();
+ uint32_t length = holder->IsJSArray()
+ ? Smi::cast(Handle<JSArray>::cast(holder)->length())->value()
+ : parameter_map->length();
+ return key < (length - 2)
+ ? handle(parameter_map->get(key + 2), isolate)
+ : Handle<Object>::cast(isolate->factory()->the_hole_value());
+ }
};
diff --git a/src/elements.h b/src/elements.h
index 1353869..bd5e722 100644
--- a/src/elements.h
+++ b/src/elements.h
@@ -65,6 +65,13 @@
// can optionally pass in the backing store to use for the check, which must
// be compatible with the ElementsKind of the ElementsAccessor. If
// backing_store is NULL, the holder->elements() is used as the backing store.
+ MUST_USE_RESULT virtual Handle<Object> Get(
+ Handle<Object> receiver,
+ Handle<JSObject> holder,
+ uint32_t key,
+ Handle<FixedArrayBase> backing_store =
+ Handle<FixedArrayBase>::null()) = 0;
+
MUST_USE_RESULT virtual MaybeObject* Get(
Object* receiver,
JSObject* holder,
@@ -124,9 +131,10 @@
int length) = 0;
// Deletes an element in an object, returning a new elements backing store.
- MUST_USE_RESULT virtual MaybeObject* Delete(JSObject* holder,
- uint32_t key,
- JSReceiver::DeleteMode mode) = 0;
+ MUST_USE_RESULT virtual Handle<Object> Delete(
+ Handle<JSObject> holder,
+ uint32_t key,
+ JSReceiver::DeleteMode mode) = 0;
// If kCopyToEnd is specified as the copy_size to CopyElements, it copies all
// of elements from source after source_start to the destination array.
@@ -141,6 +149,14 @@
// the source JSObject or JSArray in source_holder. If the holder's backing
// store is available, it can be passed in source and source_holder is
// ignored.
+ virtual void CopyElements(
+ Handle<JSObject> source_holder,
+ uint32_t source_start,
+ ElementsKind source_kind,
+ Handle<FixedArrayBase> destination,
+ uint32_t destination_start,
+ int copy_size,
+ Handle<FixedArrayBase> source = Handle<FixedArrayBase>::null()) = 0;
MUST_USE_RESULT virtual MaybeObject* CopyElements(
JSObject* source_holder,
uint32_t source_start,
diff --git a/src/execution.cc b/src/execution.cc
index 924814c..1e0a6a8 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -819,10 +819,10 @@
if (!data->do_not_cache()) {
// Fast case: see if the function has already been instantiated
int serial_number = Smi::cast(data->serial_number())->value();
- Object* elm =
- isolate->native_context()->function_cache()->
- GetElementNoExceptionThrown(isolate, serial_number);
- if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
+ Handle<JSObject> cache(isolate->native_context()->function_cache());
+ Handle<Object> elm =
+ Object::GetElementNoExceptionThrown(isolate, cache, serial_number);
+ if (elm->IsJSFunction()) return Handle<JSFunction>::cast(elm);
}
// The function has not yet been instantiated in this context; do it.
Handle<Object> args[] = { data };
diff --git a/src/factory.cc b/src/factory.cc
index 57574d1..5577607 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -69,6 +69,14 @@
}
+Handle<FixedArray> Factory::NewUninitializedFixedArray(int size) {
+ CALL_HEAP_FUNCTION(
+ isolate(),
+ isolate()->heap()->AllocateUninitializedFixedArray(size),
+ FixedArray);
+}
+
+
Handle<FixedDoubleArray> Factory::NewFixedDoubleArray(int size,
PretenureFlag pretenure) {
ASSERT(0 <= size);
@@ -377,9 +385,7 @@
// Make sure that an out of memory exception is thrown if the length
// of the new cons string is too large.
if (length > String::kMaxLength || length < 0) {
- isolate()->context()->mark_out_of_memory();
- V8::FatalProcessOutOfMemory("String concatenation result too large.");
- UNREACHABLE();
+ isolate()->ThrowInvalidStringLength();
return Handle<String>::null();
}
@@ -1132,8 +1138,7 @@
space--;
if (space > 0) {
Handle<String> arg_str = Handle<String>::cast(
- Object::GetElement(isolate(), args, i));
- CHECK_NOT_EMPTY_HANDLE(isolate(), arg_str);
+ Object::GetElementNoExceptionThrown(isolate(), args, i));
SmartArrayPointer<char> arg = arg_str->ToCString();
Vector<char> v2(p, static_cast<int>(space));
OS::StrNCpy(v2, arg.get(), space);
diff --git a/src/factory.h b/src/factory.h
index f712880..22ec4d3 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -44,7 +44,7 @@
Handle<Object> value,
PretenureFlag pretenure = NOT_TENURED);
- // Allocate a new uninitialized fixed array.
+ // Allocates a fixed array initialized with undefined values.
Handle<FixedArray> NewFixedArray(
int size,
PretenureFlag pretenure = NOT_TENURED);
@@ -54,6 +54,9 @@
int size,
PretenureFlag pretenure = NOT_TENURED);
+ // Allocates an uninitialized fixed array. It must be filled by the caller.
+ Handle<FixedArray> NewUninitializedFixedArray(int size);
+
// Allocate a new uninitialized fixed double array.
Handle<FixedDoubleArray> NewFixedDoubleArray(
int size,
diff --git a/src/func-name-inferrer.cc b/src/func-name-inferrer.cc
index 5409a4e..441113b 100644
--- a/src/func-name-inferrer.cc
+++ b/src/func-name-inferrer.cc
@@ -83,11 +83,14 @@
return MakeNameFromStackHelper(pos + 1, prev);
} else {
if (prev->length() > 0) {
+ Handle<String> name = names_stack_.at(pos).name;
+ if (prev->length() + name->length() + 1 > String::kMaxLength) return prev;
Factory* factory = isolate()->factory();
- Handle<String> curr = factory->NewConsString(
- factory->dot_string(), names_stack_.at(pos).name);
- return MakeNameFromStackHelper(pos + 1,
- factory->NewConsString(prev, curr));
+ Handle<String> curr = factory->NewConsString(factory->dot_string(), name);
+ CHECK_NOT_EMPTY_HANDLE(isolate(), curr);
+ curr = factory->NewConsString(prev, curr);
+ CHECK_NOT_EMPTY_HANDLE(isolate(), curr);
+ return MakeNameFromStackHelper(pos + 1, curr);
} else {
return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name);
}
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index b2f1708..66ce9e1 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1833,6 +1833,14 @@
ClearFlag(kLeftCanBeMinInt);
}
+ if (!a->CanBeNegative()) {
+ ClearFlag(HValue::kLeftCanBeNegative);
+ }
+
+ if (!a->CanBePositive()) {
+ ClearFlag(HValue::kLeftCanBePositive);
+ }
+
if (!a->Includes(kMinInt) || !b->Includes(-1)) {
ClearFlag(kCanOverflow);
}
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index 5a6f4c2..109cff0 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -624,6 +624,7 @@
kCanBeDivByZero,
kLeftCanBeMinInt,
kLeftCanBeNegative,
+ kLeftCanBePositive,
kAllowUndefinedAsNaN,
kIsArguments,
kTruncatingToInt32,
@@ -4105,6 +4106,8 @@
SetFlag(kCanOverflow);
SetFlag(kCanBeDivByZero);
SetFlag(kLeftCanBeMinInt);
+ SetFlag(kLeftCanBeNegative);
+ SetFlag(kLeftCanBePositive);
SetFlag(kAllowUndefinedAsNaN);
}
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index f6e22d8..282fae7 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -1793,11 +1793,8 @@
HValue* right_length) {
// Compute the combined string length and check against max string length.
HValue* length = AddUncasted<HAdd>(left_length, right_length);
- IfBuilder if_nooverflow(this);
- if_nooverflow.If<HCompareNumericAndBranch>(
- length, Add<HConstant>(String::kMaxLength), Token::LTE);
- if_nooverflow.Then();
- if_nooverflow.ElseDeopt("String length exceeds limit");
+ HValue* max_length = Add<HConstant>(String::kMaxLength);
+ Add<HBoundsCheck>(length, max_length);
return length;
}
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 3e36d71..cd283cf 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -1665,8 +1665,31 @@
DeoptimizeIf(zero, instr->environment());
}
- // TODO(svenpanne) Add correction terms.
- __ TruncatingDiv(dividend, divisor);
+ // Easy case: We need no dynamic check for the dividend and the flooring
+ // division is the same as the truncating division.
+ if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
+ __ TruncatingDiv(dividend, Abs(divisor));
+ if (divisor < 0) __ neg(edx);
+ return;
+ }
+
+ // In the general case we may need to adjust before and after the truncating
+ // division to get a flooring division.
+ Register temp = ToRegister(instr->temp3());
+ ASSERT(!temp.is(dividend) && !temp.is(eax) && !temp.is(edx));
+ Label needs_adjustment, done;
+ __ cmp(dividend, Immediate(0));
+ __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
+ __ TruncatingDiv(dividend, Abs(divisor));
+ if (divisor < 0) __ neg(edx);
+ __ jmp(&done, Label::kNear);
+ __ bind(&needs_adjustment);
+ __ lea(temp, Operand(dividend, divisor > 0 ? 1 : -1));
+ __ TruncatingDiv(temp, Abs(divisor));
+ if (divisor < 0) __ neg(edx);
+ __ dec(edx);
+ __ bind(&done);
}
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 930b7ed..de3bf9e 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -1427,24 +1427,30 @@
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp1 = FixedTemp(eax);
LOperand* temp2 = FixedTemp(edx);
+ LOperand* temp3 =
+ ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
+ NULL : TempRegister();
LInstruction* result =
DefineFixed(new(zone()) LFlooringDivByConstI(dividend,
divisor,
temp1,
- temp2),
+ temp2,
+ temp3),
edx);
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
- return can_deopt ? AssignEnvironment(result) : result;
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
if (instr->RightIsPowerOf2()) {
return DoFlooringDivByPowerOf2I(instr);
- } else if (false && instr->right()->IsConstant()) {
- return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable.
+ } else if (instr->right()->IsConstant()) {
+ return DoFlooringDivByConstI(instr);
} else {
return DoDivI(instr);
}
diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
index fa4ea0f..7964b7f 100644
--- a/src/ia32/lithium-ia32.h
+++ b/src/ia32/lithium-ia32.h
@@ -778,22 +778,25 @@
};
-class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
+class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 3> {
public:
LFlooringDivByConstI(LOperand* dividend,
int32_t divisor,
LOperand* temp1,
- LOperand* temp2) {
+ LOperand* temp2,
+ LOperand* temp3) {
inputs_[0] = dividend;
divisor_ = divisor;
temps_[0] = temp1;
temps_[1] = temp2;
+ temps_[2] = temp3;
}
LOperand* dividend() { return inputs_[0]; }
int32_t divisor() const { return divisor_; }
LOperand* temp1() { return temps_[0]; }
LOperand* temp2() { return temps_[1]; }
+ LOperand* temp3() { return temps_[2]; }
DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)
diff --git a/src/ic.cc b/src/ic.cc
index 4924dbb..89bd87a 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -1452,7 +1452,8 @@
if (IsTransitionStoreMode(store_mode)) {
transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode);
}
- if (receiver_map.is_identical_to(previous_receiver_map) ||
+ if ((receiver_map.is_identical_to(previous_receiver_map) &&
+ IsTransitionStoreMode(store_mode)) ||
IsTransitionOfMonomorphicTarget(
MapToType<HeapType>(transitioned_receiver_map, isolate()))) {
// If the "old" and "new" maps are in the same elements map family, or
diff --git a/src/isolate.cc b/src/isolate.cc
index 50b402b..fed4b4a 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -951,6 +951,12 @@
}
+Failure* Isolate::ThrowInvalidStringLength() {
+ return Throw(*factory()->NewRangeError(
+ "invalid_string_length", HandleVector<Object>(NULL, 0)));
+}
+
+
void Isolate::ScheduleThrow(Object* exception) {
// When scheduling a throw we first throw the exception to get the
// error reporting if it is uncaught before rescheduling it.
diff --git a/src/isolate.h b/src/isolate.h
index d1f7003..0a24404 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -789,6 +789,7 @@
// Return pending location if any or unfilled structure.
MessageLocation GetMessageLocation();
Failure* ThrowIllegalOperation();
+ Failure* ThrowInvalidStringLength();
// Promote a scheduled exception to pending. Asserts has_scheduled_exception.
Failure* PromoteScheduledException();
diff --git a/src/json-stringifier.h b/src/json-stringifier.h
index 175b9a1..a75b3de 100644
--- a/src/json-stringifier.h
+++ b/src/json-stringifier.h
@@ -51,6 +51,8 @@
enum Result { UNCHANGED, SUCCESS, EXCEPTION, CIRCULAR, STACK_OVERFLOW };
+ void Accumulate();
+
void Extend();
void ChangeEncoding();
@@ -178,6 +180,7 @@
int current_index_;
int part_length_;
bool is_ascii_;
+ bool overflowed_;
static const int kJsonEscapeTableEntrySize = 8;
static const char* const JsonEscapeTable;
@@ -254,7 +257,10 @@
BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
- : isolate_(isolate), current_index_(0), is_ascii_(true) {
+ : isolate_(isolate),
+ current_index_(0),
+ is_ascii_(true),
+ overflowed_(false) {
factory_ = isolate_->factory();
accumulator_store_ = Handle<JSValue>::cast(
factory_->ToObject(factory_->empty_string()));
@@ -269,9 +275,12 @@
switch (SerializeObject(object)) {
case UNCHANGED:
return isolate_->heap()->undefined_value();
- case SUCCESS:
+ case SUCCESS: {
ShrinkCurrentPart();
- return *factory_->NewConsString(accumulator(), current_part_);
+ Accumulate();
+ if (overflowed_) return isolate_->ThrowInvalidStringLength();
+ return *accumulator();
+ }
case CIRCULAR:
return isolate_->Throw(*factory_->NewTypeError(
"circular_structure", HandleVector<Object>(NULL, 0)));
@@ -486,7 +495,9 @@
part_length_ = kInitialPartLength; // Allocate conservatively.
Extend(); // Attach current part and allocate new part.
// Attach result string to the accumulator.
- set_accumulator(factory_->NewConsString(accumulator(), result_string));
+ Handle<String> cons = factory_->NewConsString(accumulator(), result_string);
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate_, cons, EXCEPTION);
+ set_accumulator(cons);
return SUCCESS;
}
@@ -708,8 +719,20 @@
}
+void BasicJsonStringifier::Accumulate() {
+ if (accumulator()->length() + current_part_->length() > String::kMaxLength) {
+ // Screw it. Simply set the flag and carry on. Throw exception at the end.
+ // We most likely will trigger a real OOM before even reaching this point.
+ set_accumulator(factory_->empty_string());
+ overflowed_ = true;
+ } else {
+ set_accumulator(factory_->NewConsString(accumulator(), current_part_));
+ }
+}
+
+
void BasicJsonStringifier::Extend() {
- set_accumulator(factory_->NewConsString(accumulator(), current_part_));
+ Accumulate();
if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
part_length_ *= kPartLengthGrowthFactor;
}
@@ -724,7 +747,7 @@
void BasicJsonStringifier::ChangeEncoding() {
ShrinkCurrentPart();
- set_accumulator(factory_->NewConsString(accumulator(), current_part_));
+ Accumulate();
current_part_ = factory_->NewRawTwoByteString(part_length_);
current_index_ = 0;
is_ascii_ = false;
diff --git a/src/liveedit.cc b/src/liveedit.cc
index aa906b2..a812b75 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -669,13 +669,13 @@
field_position,
Handle<Smi>(Smi::FromInt(value), isolate()));
}
- Object* GetField(int field_position) {
- return array_->GetElementNoExceptionThrown(isolate(), field_position);
+ Handle<Object> GetField(int field_position) {
+ return Object::GetElementNoExceptionThrown(
+ isolate(), array_, field_position);
}
int GetSmiValueField(int field_position) {
- Object* res = GetField(field_position);
- CHECK(res->IsSmi());
- return Smi::cast(res)->value();
+ Handle<Object> res = GetField(field_position);
+ return Handle<Smi>::cast(res)->value();
}
private:
@@ -724,17 +724,15 @@
return this->GetSmiValueField(kParentIndexOffset_);
}
Handle<Code> GetFunctionCode() {
- Object* element = this->GetField(kCodeOffset_);
- CHECK(element->IsJSValue());
- Handle<JSValue> value_wrapper(JSValue::cast(element));
+ Handle<Object> element = this->GetField(kCodeOffset_);
+ Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
CHECK(raw_result->IsCode());
return Handle<Code>::cast(raw_result);
}
Handle<Object> GetCodeScopeInfo() {
- Object* element = this->GetField(kCodeScopeInfoOffset_);
- CHECK(element->IsJSValue());
- return UnwrapJSValue(Handle<JSValue>(JSValue::cast(element)));
+ Handle<Object> element = this->GetField(kCodeScopeInfoOffset_);
+ return UnwrapJSValue(Handle<JSValue>::cast(element));
}
int GetStartPosition() {
return this->GetSmiValueField(kStartPositionOffset_);
@@ -767,8 +765,8 @@
public:
static bool IsInstance(Handle<JSArray> array) {
return array->length() == Smi::FromInt(kSize_) &&
- array->GetElementNoExceptionThrown(
- array->GetIsolate(), kSharedInfoOffset_)->IsJSValue();
+ Object::GetElementNoExceptionThrown(
+ array->GetIsolate(), array, kSharedInfoOffset_)->IsJSValue();
}
explicit SharedInfoWrapper(Handle<JSArray> array)
@@ -785,9 +783,8 @@
this->SetSmiValueField(kEndPositionOffset_, end_position);
}
Handle<SharedFunctionInfo> GetInfo() {
- Object* element = this->GetField(kSharedInfoOffset_);
- CHECK(element->IsJSValue());
- Handle<JSValue> value_wrapper(JSValue::cast(element));
+ Handle<Object> element = this->GetField(kSharedInfoOffset_);
+ Handle<JSValue> value_wrapper = Handle<JSValue>::cast(element);
return UnwrapSharedFunctionInfoFromJSValue(value_wrapper);
}
@@ -826,8 +823,8 @@
HandleScope scope(isolate());
FunctionInfoWrapper info =
FunctionInfoWrapper::cast(
- result_->GetElementNoExceptionThrown(
- isolate(), current_parent_index_));
+ *Object::GetElementNoExceptionThrown(
+ isolate(), result_, current_parent_index_));
current_parent_index_ = info.GetParentIndex();
}
@@ -836,8 +833,8 @@
void FunctionCode(Handle<Code> function_code) {
FunctionInfoWrapper info =
FunctionInfoWrapper::cast(
- result_->GetElementNoExceptionThrown(
- isolate(), current_parent_index_));
+ *Object::GetElementNoExceptionThrown(
+ isolate(), result_, current_parent_index_));
info.SetFunctionCode(function_code,
Handle<HeapObject>(isolate()->heap()->null_value()));
}
@@ -851,8 +848,8 @@
}
FunctionInfoWrapper info =
FunctionInfoWrapper::cast(
- result_->GetElementNoExceptionThrown(
- isolate(), current_parent_index_));
+ *Object::GetElementNoExceptionThrown(
+ isolate(), result_, current_parent_index_));
info.SetFunctionCode(Handle<Code>(shared->code()),
Handle<HeapObject>(shared->scope_info()));
info.SetSharedFunctionInfo(shared);
@@ -987,7 +984,7 @@
for (int i = 0; i < len; i++) {
Handle<SharedFunctionInfo> info(
SharedFunctionInfo::cast(
- array->GetElementNoExceptionThrown(isolate, i)));
+ *Object::GetElementNoExceptionThrown(isolate, array, i)));
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(isolate);
Handle<String> name_handle(String::cast(info->name()));
info_wrapper.SetProperties(name_handle, info->start_position(),
@@ -1361,23 +1358,24 @@
Isolate* isolate = position_change_array->GetIsolate();
// TODO(635): binary search may be used here
for (int i = 0; i < array_len; i += 3) {
- Object* element =
- position_change_array->GetElementNoExceptionThrown(isolate, i);
+ HandleScope scope(isolate);
+ Handle<Object> element = Object::GetElementNoExceptionThrown(
+ isolate, position_change_array, i);
CHECK(element->IsSmi());
- int chunk_start = Smi::cast(element)->value();
+ int chunk_start = Handle<Smi>::cast(element)->value();
if (original_position < chunk_start) {
break;
}
- element = position_change_array->GetElementNoExceptionThrown(isolate,
- i + 1);
+ element = Object::GetElementNoExceptionThrown(
+ isolate, position_change_array, i + 1);
CHECK(element->IsSmi());
- int chunk_end = Smi::cast(element)->value();
+ int chunk_end = Handle<Smi>::cast(element)->value();
// Position mustn't be inside a chunk.
ASSERT(original_position >= chunk_end);
- element = position_change_array->GetElementNoExceptionThrown(isolate,
- i + 2);
+ element = Object::GetElementNoExceptionThrown(
+ isolate, position_change_array, i + 2);
CHECK(element->IsSmi());
- int chunk_changed_end = Smi::cast(element)->value();
+ int chunk_changed_end = Handle<Smi>::cast(element)->value();
position_diff = chunk_changed_end - chunk_end;
}
@@ -1472,7 +1470,6 @@
code->instruction_start());
{
- DisallowHeapAllocation no_allocation;
for (RelocIterator it(*code); !it.done(); it.next()) {
RelocInfo* rinfo = it.rinfo();
if (RelocInfo::IsPosition(rinfo->rmode())) {
@@ -1631,10 +1628,10 @@
Isolate* isolate = shared_info_array->GetIsolate();
int len = GetArrayLength(shared_info_array);
for (int i = 0; i < len; i++) {
- Object* element =
- shared_info_array->GetElementNoExceptionThrown(isolate, i);
- CHECK(element->IsJSValue());
- Handle<JSValue> jsvalue(JSValue::cast(element));
+ HandleScope scope(isolate);
+ Handle<Object> element =
+ Object::GetElementNoExceptionThrown(isolate, shared_info_array, i);
+ Handle<JSValue> jsvalue = Handle<JSValue>::cast(element);
Handle<SharedFunctionInfo> shared =
UnwrapSharedFunctionInfoFromJSValue(jsvalue);
@@ -1949,8 +1946,8 @@
// Replace "blocked on active" with "replaced on active" status.
for (int i = 0; i < array_len; i++) {
- Handle<Object> obj = Object::GetElement(isolate, result, i);
- CHECK_NOT_EMPTY_HANDLE(isolate, obj);
+ Handle<Object> obj =
+ Object::GetElementNoExceptionThrown(isolate, result, i);
if (*obj == Smi::FromInt(LiveEdit::FUNCTION_BLOCKED_ON_ACTIVE_STACK)) {
Handle<Object> replaced(
Smi::FromInt(LiveEdit::FUNCTION_REPLACED_ON_ACTIVE_STACK), isolate);
diff --git a/src/log.cc b/src/log.cc
index e01692e..942170c 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1206,9 +1206,9 @@
if (c == '%' && i <= format.length() - 2) {
i++;
ASSERT('0' <= format[i] && format[i] <= '9');
- Handle<Object> obj = Object::GetElement(isolate_, args, format[i] - '0');
// No exception expected when getting an element from an array literal.
- CHECK_NOT_EMPTY_HANDLE(isolate_, obj);
+ Handle<Object> obj =
+ Object::GetElementNoExceptionThrown(isolate_, args, format[i] - '0');
i++;
switch (format[i]) {
case 's':
diff --git a/src/messages.js b/src/messages.js
index e6365a4..bc14785 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -157,7 +157,7 @@
strict_eval_arguments: ["Unexpected eval or arguments in strict mode"],
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)"],
+ too_many_variables: ["Too many variables declared (only 4194303 allowed)"],
strict_param_dupe: ["Strict mode function may not have duplicate parameter names"],
strict_octal_literal: ["Octal literals are not allowed in strict mode."],
strict_duplicate_property: ["Duplicate data property in object literal not allowed in strict mode"],
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 83f11e7..811b2f9 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1077,11 +1077,20 @@
}
-Object* Object::GetElementNoExceptionThrown(Isolate* isolate, uint32_t index) {
- MaybeObject* maybe = GetElementWithReceiver(isolate, this, index);
- ASSERT(!maybe->IsFailure());
- Object* result = NULL; // Initialization to please compiler.
- maybe->ToObject(&result);
+static Handle<Object> GetElementNoExceptionThrownHelper(Isolate* isolate,
+ Handle<Object> object,
+ uint32_t index) {
+ CALL_HEAP_FUNCTION(isolate,
+ object->GetElementWithReceiver(isolate, *object, index),
+ Object);
+}
+
+Handle<Object> Object::GetElementNoExceptionThrown(Isolate* isolate,
+ Handle<Object> object,
+ uint32_t index) {
+ Handle<Object> result =
+ GetElementNoExceptionThrownHelper(isolate, object, index);
+ CHECK_NOT_EMPTY_HANDLE(isolate, result);
return result;
}
diff --git a/src/objects.cc b/src/objects.cc
index 897c52a..88e7234 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5103,18 +5103,6 @@
}
-// TODO(mstarzinger): Temporary wrapper until handlified.
-static Handle<Object> AccessorDelete(Handle<JSObject> object,
- uint32_t index,
- JSObject::DeleteMode mode) {
- CALL_HEAP_FUNCTION(object->GetIsolate(),
- object->GetElementsAccessor()->Delete(*object,
- index,
- mode),
- Object);
-}
-
-
Handle<Object> JSObject::DeleteElementWithInterceptor(Handle<JSObject> object,
uint32_t index) {
Isolate* isolate = object->GetIsolate();
@@ -5141,7 +5129,8 @@
// Rebox CustomArguments::kReturnValueOffset before returning.
return handle(*result_internal, isolate);
}
- Handle<Object> delete_result = AccessorDelete(object, index, NORMAL_DELETION);
+ Handle<Object> delete_result = object->GetElementsAccessor()->Delete(
+ object, index, NORMAL_DELETION);
RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
return delete_result;
}
@@ -5190,8 +5179,7 @@
if (object->GetLocalElementAccessorPair(index) != NULL) {
old_value = Handle<Object>::cast(factory->the_hole_value());
} else {
- old_value = Object::GetElement(isolate, object, index);
- CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
+ old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
}
}
}
@@ -5201,7 +5189,7 @@
if (object->HasIndexedInterceptor() && mode != FORCE_DELETION) {
result = DeleteElementWithInterceptor(object, index);
} else {
- result = AccessorDelete(object, index, mode);
+ result = object->GetElementsAccessor()->Delete(object, index, mode);
}
if (should_enqueue_change_record && !HasLocalElement(object, index)) {
@@ -6360,8 +6348,7 @@
if (is_element) {
preexists = HasLocalElement(object, index);
if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
- old_value = Object::GetElement(isolate, object, index);
- CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
+ old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
}
} else {
LookupResult lookup(isolate);
@@ -11343,8 +11330,7 @@
if (object->GetLocalElementAccessorPair(index) != NULL) {
value = Handle<Object>::cast(isolate->factory()->the_hole_value());
} else {
- value = Object::GetElement(isolate, object, index);
- CHECK_NOT_EMPTY_HANDLE(isolate, value);
+ value = Object::GetElementNoExceptionThrown(isolate, object, index);
}
old_values->Add(value);
indices->Add(index);
@@ -12564,8 +12550,7 @@
if (old_attributes != ABSENT) {
if (object->GetLocalElementAccessorPair(index) == NULL) {
- old_value = Object::GetElement(isolate, object, index);
- CHECK_NOT_EMPTY_HANDLE(isolate, old_value);
+ old_value = Object::GetElementNoExceptionThrown(isolate, object, index);
}
} else if (object->IsJSArray()) {
// Store old array length in case adding an element grows the array.
@@ -12611,8 +12596,8 @@
} else if (old_value->IsTheHole()) {
EnqueueChangeRecord(object, "reconfigure", name, old_value);
} else {
- Handle<Object> new_value = Object::GetElement(isolate, object, index);
- CHECK_NOT_EMPTY_HANDLE(isolate, new_value);
+ Handle<Object> new_value =
+ Object::GetElementNoExceptionThrown(isolate, object, index);
bool value_changed = !old_value->SameValue(*new_value);
if (old_attributes != new_attributes) {
if (!value_changed) old_value = isolate->factory()->the_hole_value();
diff --git a/src/objects.h b/src/objects.h
index a87e389..25dbcbb 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1586,7 +1586,10 @@
uint32_t index);
// For use when we know that no exception can be thrown.
- inline Object* GetElementNoExceptionThrown(Isolate* isolate, uint32_t index);
+ static inline Handle<Object> GetElementNoExceptionThrown(
+ Isolate* isolate,
+ Handle<Object> object,
+ uint32_t index);
MUST_USE_RESULT MaybeObject* GetElementWithReceiver(Isolate* isolate,
Object* receiver,
uint32_t index);
diff --git a/src/parser.cc b/src/parser.cc
index 0d1ba00..9fe6a3b 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -2922,6 +2922,7 @@
Factory* heap_factory = isolate()->factory();
Handle<String> tempstr =
heap_factory->NewConsString(heap_factory->dot_for_string(), name);
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate(), tempstr, 0);
Handle<String> tempname = heap_factory->InternalizeString(tempstr);
Variable* temp = scope_->DeclarationScope()->NewTemporary(tempname);
VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
diff --git a/src/parser.h b/src/parser.h
index 3d2f032..f3984e8 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -618,7 +618,14 @@
private:
friend class ParserTraits;
- static const int kMaxNumFunctionLocals = 131071; // 2^17-1
+ // Limit the allowed number of local variables in a function. The hard limit
+ // is that offsets computed by FullCodeGenerator::StackOperand and similar
+ // functions are ints, and they should not overflow. In addition, accessing
+ // local variables creates user-controlled constants in the generated code,
+ // and we don't want too much user-controlled memory inside the code (this was
+ // the reason why this limit was introduced in the first place; see
+ // https://codereview.chromium.org/7003030/ ).
+ static const int kMaxNumFunctionLocals = 4194303; // 2^22-1
enum Mode {
PARSE_LAZILY,
diff --git a/src/preparser.cc b/src/preparser.cc
index 398f327..474e642 100644
--- a/src/preparser.cc
+++ b/src/preparser.cc
@@ -874,7 +874,7 @@
if (result.IsThis()) {
result = Expression::ThisProperty();
} else {
- result = Expression::Default();
+ result = Expression::Property();
}
break;
}
@@ -891,7 +891,7 @@
if (result.IsThis()) {
result = Expression::ThisProperty();
} else {
- result = Expression::Default();
+ result = Expression::Property();
}
break;
}
@@ -913,13 +913,17 @@
if (peek() == Token::NEW) {
Consume(Token::NEW);
ParseMemberWithNewPrefixesExpression(CHECK_OK);
+ Expression expression = Expression::Default();
if (peek() == Token::LPAREN) {
// NewExpression with arguments.
ParseArguments(CHECK_OK);
- // The expression can still continue with . or [ after the arguments.
- ParseMemberExpressionContinuation(Expression::Default(), CHECK_OK);
+ // The expression can still continue with . or [ after the arguments. Here
+ // we need to transmit the "is valid left hand side" property of the
+ // expression.
+ expression =
+ ParseMemberExpressionContinuation(Expression::Default(), CHECK_OK);
}
- return Expression::Default();
+ return expression;
}
// No 'new' keyword.
return ParseMemberExpression(ok);
@@ -980,7 +984,7 @@
if (expression.IsThis()) {
expression = Expression::ThisProperty();
} else {
- expression = Expression::Default();
+ expression = Expression::Property();
}
break;
}
@@ -990,7 +994,7 @@
if (expression.IsThis()) {
expression = Expression::ThisProperty();
} else {
- expression = Expression::Default();
+ expression = Expression::Property();
}
break;
}
@@ -1102,7 +1106,6 @@
int end_position = scanner()->location().end_pos;
CheckOctalLiteral(start_position, end_position, CHECK_OK);
- return Expression::StrictFunction();
}
return Expression::Default();
diff --git a/src/preparser.h b/src/preparser.h
index 05ff972..b6d97f7 100644
--- a/src/preparser.h
+++ b/src/preparser.h
@@ -554,8 +554,8 @@
return PreParserExpression(kThisPropertyExpression);
}
- static PreParserExpression StrictFunction() {
- return PreParserExpression(kStrictFunctionExpression);
+ static PreParserExpression Property() {
+ return PreParserExpression(kPropertyExpression);
}
bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; }
@@ -576,7 +576,9 @@
bool IsThisProperty() { return code_ == kThisPropertyExpression; }
- bool IsStrictFunction() { return code_ == kStrictFunctionExpression; }
+ bool IsProperty() {
+ return code_ == kPropertyExpression || code_ == kThisPropertyExpression;
+ }
// Dummy implementation for making expression->AsCall() work (see below).
PreParserExpression* operator->() { return this; }
@@ -590,9 +592,11 @@
void set_index(int index) {} // For YieldExpressions
private:
- // First two/three bits are used as flags.
- // Bit 0 and 1 represent identifiers or strings literals, and are
- // mutually exclusive, but can both be absent.
+ // Least significant 2 bits are used as flags. Bits 0 and 1 represent
+ // identifiers or strings literals, and are mutually exclusive, but can both
+ // be absent. If the expression is an identifier or a string literal, the
+ // other bits describe the type (see PreParserIdentifier::Type and string
+ // literal constants below).
enum {
kUnknownExpression = 0,
// Identifiers
@@ -604,10 +608,11 @@
kUseStrictString = kStringLiteralFlag | 8,
kStringLiteralMask = kUseStrictString,
- // Below here applies if neither identifier nor string literal.
- kThisExpression = 4,
- kThisPropertyExpression = 8,
- kStrictFunctionExpression = 12
+ // Below here applies if neither identifier nor string literal. Reserve the
+ // 2 least significant bits for flags.
+ kThisExpression = 1 << 2,
+ kThisPropertyExpression = 2 << 2,
+ kPropertyExpression = 3 << 2
};
explicit PreParserExpression(int expression_code) : code_(expression_code) {}
@@ -830,8 +835,7 @@
// Determine whether the expression is a valid assignment left-hand side.
static bool IsValidLeftHandSide(PreParserExpression expression) {
- // TODO(marja): check properly; for now, leave it to parser.
- return true;
+ return expression.IsIdentifier() || expression.IsProperty();
}
static PreParserExpression MarkExpressionAsLValue(
diff --git a/src/runtime.cc b/src/runtime.cc
index 762b7a5..cc7942f 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -3330,7 +3330,8 @@
array_builder_(heap->isolate(), estimated_part_count),
subject_(subject),
character_count_(0),
- is_ascii_(subject->IsOneByteRepresentation()) {
+ is_ascii_(subject->IsOneByteRepresentation()),
+ overflowed_(false) {
// Require a non-zero initial size. Ensures that doubling the size to
// extend the array will work.
ASSERT(estimated_part_count > 0);
@@ -3378,6 +3379,11 @@
Handle<String> ToString() {
+ if (overflowed_) {
+ heap_->isolate()->ThrowInvalidStringLength();
+ return Handle<String>();
+ }
+
if (array_builder_.length() == 0) {
return heap_->isolate()->factory()->empty_string();
}
@@ -3409,7 +3415,7 @@
void IncrementCharacterCount(int by) {
if (character_count_ > String::kMaxLength - by) {
- V8::FatalProcessOutOfMemory("String.replace result too large.");
+ overflowed_ = true;
}
character_count_ += by;
}
@@ -3436,6 +3442,7 @@
Handle<String> subject_;
int character_count_;
bool is_ascii_;
+ bool overflowed_;
};
@@ -4034,7 +4041,9 @@
capture_count,
global_cache.LastSuccessfulMatch());
- return *(builder.ToString());
+ Handle<String> result = builder.ToString();
+ RETURN_IF_EMPTY_HANDLE(isolate, result);
+ return *result;
}
@@ -4180,8 +4189,8 @@
replace,
found,
recursion_limit - 1);
- if (*found) return isolate->factory()->NewConsString(new_first, second);
if (new_first.is_null()) return new_first;
+ if (*found) return isolate->factory()->NewConsString(new_first, second);
Handle<String> new_second =
StringReplaceOneCharWithString(isolate,
@@ -4190,8 +4199,8 @@
replace,
found,
recursion_limit - 1);
- if (*found) return isolate->factory()->NewConsString(first, new_second);
if (new_second.is_null()) return new_second;
+ if (*found) return isolate->factory()->NewConsString(first, new_second);
return subject;
} else {
@@ -4200,6 +4209,7 @@
*found = true;
Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, cons1, Handle<String>());
Handle<String> second =
isolate->factory()->NewSubString(subject, index + 1, subject->length());
return isolate->factory()->NewConsString(cons1, second);
@@ -4225,6 +4235,7 @@
&found,
kRecursionLimit);
if (!result.is_null()) return *result;
+ if (isolate->has_pending_exception()) return Failure::Exception();
return *StringReplaceOneCharWithString(isolate,
FlattenGetString(subject),
search,
@@ -6225,7 +6236,7 @@
Handle<String> result = string->IsOneByteRepresentationUnderneath()
? URIEscape::Escape<uint8_t>(isolate, source)
: URIEscape::Escape<uc16>(isolate, source);
- if (result.is_null()) return Failure::OutOfMemoryException(0x12);
+ RETURN_IF_EMPTY_HANDLE(isolate, result);
return *result;
}
@@ -6359,9 +6370,9 @@
int char_length = mapping->get(current, 0, chars);
if (char_length == 0) char_length = 1;
current_length += char_length;
- if (current_length > Smi::kMaxValue) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x13);
+ if (current_length > String::kMaxLength) {
+ AllowHeapAllocation allocate_error_and_return;
+ return isolate->ThrowInvalidStringLength();
}
}
// Try again with the real length. Return signed if we need
@@ -7016,7 +7027,9 @@
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
isolate->counters()->string_add_runtime()->Increment();
- return *isolate->factory()->NewConsString(str1, str2);
+ Handle<String> result = isolate->factory()->NewConsString(str1, str2);
+ RETURN_IF_EMPTY_HANDLE(isolate, result);
+ return *result;
}
@@ -7063,10 +7076,7 @@
HandleScope scope(isolate);
ASSERT(args.length() == 3);
CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x14);
- }
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
int array_length = args.smi_at(1);
CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
@@ -7140,8 +7150,7 @@
return isolate->Throw(isolate->heap()->illegal_argument_string());
}
if (increment > String::kMaxLength - position) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x15);
+ return isolate->ThrowInvalidStringLength();
}
position += increment;
}
@@ -7176,20 +7185,15 @@
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
- SealHandleScope shs(isolate);
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
- CONVERT_ARG_CHECKED(JSArray, array, 0);
- if (!args[1]->IsSmi()) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x16);
- }
+ CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
+ if (!args[1]->IsSmi()) return isolate->ThrowInvalidStringLength();
int array_length = args.smi_at(1);
- CONVERT_ARG_CHECKED(String, separator, 2);
+ CONVERT_ARG_HANDLE_CHECKED(String, separator, 2);
+ RUNTIME_ASSERT(array->HasFastObjectElements());
- if (!array->HasFastObjectElements()) {
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
- FixedArray* fixed_array = FixedArray::cast(array->elements());
+ Handle<FixedArray> fixed_array(FixedArray::cast(array->elements()));
if (fixed_array->length() < array_length) {
array_length = fixed_array->length();
}
@@ -7198,38 +7202,32 @@
return isolate->heap()->empty_string();
} else if (array_length == 1) {
Object* first = fixed_array->get(0);
- if (first->IsString()) return first;
+ RUNTIME_ASSERT(first->IsString());
+ return first;
}
int separator_length = separator->length();
int max_nof_separators =
(String::kMaxLength + separator_length - 1) / separator_length;
if (max_nof_separators < (array_length - 1)) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x17);
+ return isolate->ThrowInvalidStringLength();
}
int length = (array_length - 1) * separator_length;
for (int i = 0; i < array_length; i++) {
Object* element_obj = fixed_array->get(i);
- if (!element_obj->IsString()) {
- // TODO(1161): handle this case.
- return isolate->Throw(isolate->heap()->illegal_argument_string());
- }
+ RUNTIME_ASSERT(element_obj->IsString());
String* element = String::cast(element_obj);
int increment = element->length();
if (increment > String::kMaxLength - length) {
- isolate->context()->mark_out_of_memory();
- return Failure::OutOfMemoryException(0x18);
+ return isolate->ThrowInvalidStringLength();
}
length += increment;
}
- Object* object;
- { MaybeObject* maybe_object =
- isolate->heap()->AllocateRawTwoByteString(length);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- SeqTwoByteString* answer = SeqTwoByteString::cast(object);
+ Handle<SeqTwoByteString> answer =
+ isolate->factory()->NewRawTwoByteString(length);
+
+ DisallowHeapAllocation no_gc;
uc16* sink = answer->GetChars();
#ifdef DEBUG
@@ -7237,13 +7235,14 @@
#endif
String* first = String::cast(fixed_array->get(0));
+ String* seperator_raw = *separator;
int first_length = first->length();
String::WriteToFlat(first, sink, 0, first_length);
sink += first_length;
for (int i = 1; i < array_length; i++) {
ASSERT(sink + separator_length <= end);
- String::WriteToFlat(separator, sink, 0, separator_length);
+ String::WriteToFlat(seperator_raw, sink, 0, separator_length);
sink += separator_length;
String* element = String::cast(fixed_array->get(i));
@@ -7256,7 +7255,7 @@
// Use %_FastAsciiArrayJoin instead.
ASSERT(!answer->IsOneByteRepresentation());
- return answer;
+ return *answer;
}
template <typename Char>
@@ -7357,9 +7356,7 @@
// Throw an exception if the resulting string is too large. See
// https://code.google.com/p/chromium/issues/detail?id=336820
// for details.
- return isolate->Throw(*isolate->factory()->
- NewRangeError("invalid_string_length",
- HandleVector<Object>(NULL, 0)));
+ return isolate->ThrowInvalidStringLength();
}
if (is_ascii) {
@@ -13045,20 +13042,20 @@
// args[1]: constructor function for instances to exclude (Mirror)
// args[2]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
- SealHandleScope shs(isolate);
+ HandleScope scope(isolate);
ASSERT(args.length() == 3);
// First perform a full GC in order to avoid references from dead objects.
- isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
- "%DebugReferencedBy");
+ Heap* heap = isolate->heap();
+ heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugReferencedBy");
// The heap iterator reserves the right to do a GC to make the heap iterable.
// Due to the GC above we know it won't need to do that, but it seems cleaner
// to get the heap iterator constructed before we start having unprotected
// Object* locals that are not protected by handles.
// Check parameters.
- CONVERT_ARG_CHECKED(JSObject, target, 0);
- Object* instance_filter = args[1];
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, target, 0);
+ Handle<Object> instance_filter = args.at<Object>(1);
RUNTIME_ASSERT(instance_filter->IsUndefined() ||
instance_filter->IsJSObject());
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
@@ -13066,40 +13063,36 @@
// Get the constructor function for context extension and arguments array.
- JSObject* arguments_boilerplate =
- isolate->context()->native_context()->sloppy_arguments_boilerplate();
- JSFunction* arguments_function =
- JSFunction::cast(arguments_boilerplate->map()->constructor());
+ Handle<JSObject> arguments_boilerplate(
+ isolate->context()->native_context()->sloppy_arguments_boilerplate());
+ Handle<JSFunction> arguments_function(
+ JSFunction::cast(arguments_boilerplate->map()->constructor()));
// Get the number of referencing objects.
int count;
- Heap* heap = isolate->heap();
HeapIterator heap_iterator(heap);
count = DebugReferencedBy(&heap_iterator,
- target, instance_filter, max_references,
- NULL, 0, arguments_function);
+ *target, *instance_filter, max_references,
+ NULL, 0, *arguments_function);
// Allocate an array to hold the result.
- Object* object;
- { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- FixedArray* instances = FixedArray::cast(object);
+ Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
// Fill the referencing objects.
// AllocateFixedArray above does not make the heap non-iterable.
ASSERT(heap->IsHeapIterable());
HeapIterator heap_iterator2(heap);
count = DebugReferencedBy(&heap_iterator2,
- target, instance_filter, max_references,
- instances, count, arguments_function);
+ *target, *instance_filter, max_references,
+ *instances, count, *arguments_function);
// Return result as JS array.
- Object* result;
- MaybeObject* maybe_result = heap->AllocateJSObject(
+ Handle<JSFunction> constructor(
isolate->context()->native_context()->array_function());
- if (!maybe_result->ToObject(&result)) return maybe_result;
- return JSArray::cast(result)->SetContent(instances);
+
+ Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
+ isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
+ return *result;
}
@@ -13139,7 +13132,7 @@
// args[0]: the constructor to find instances of
// args[1]: the the maximum number of objects to return
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
- SealHandleScope shs(isolate);
+ HandleScope scope(isolate);
ASSERT(args.length() == 2);
// First perform a full GC in order to avoid dead objects.
@@ -13147,7 +13140,7 @@
heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
// Check parameters.
- CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
+ CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
RUNTIME_ASSERT(max_references >= 0);
@@ -13155,34 +13148,29 @@
int count;
HeapIterator heap_iterator(heap);
count = DebugConstructedBy(&heap_iterator,
- constructor,
+ *constructor,
max_references,
NULL,
0);
// Allocate an array to hold the result.
- Object* object;
- { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
- if (!maybe_object->ToObject(&object)) return maybe_object;
- }
- FixedArray* instances = FixedArray::cast(object);
+ Handle<FixedArray> instances = isolate->factory()->NewFixedArray(count);
- ASSERT(isolate->heap()->IsHeapIterable());
+ ASSERT(heap->IsHeapIterable());
// Fill the referencing objects.
HeapIterator heap_iterator2(heap);
count = DebugConstructedBy(&heap_iterator2,
- constructor,
+ *constructor,
max_references,
- instances,
+ *instances,
count);
// Return result as JS array.
- Object* result;
- { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
+ Handle<JSFunction> array_function(
isolate->context()->native_context()->array_function());
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
- return JSArray::cast(result)->SetContent(instances);
+ Handle<JSObject> result = isolate->factory()->NewJSObject(array_function);
+ isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
+ return *result;
}
diff --git a/src/uri.h b/src/uri.h
index ee1baeb..81ec0c5 100644
--- a/src/uri.h
+++ b/src/uri.h
@@ -264,7 +264,8 @@
// We don't allow strings that are longer than a maximal length.
ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow.
if (escaped_length > String::kMaxLength) {
- isolate->context()->mark_out_of_memory();
+ AllowHeapAllocation allocate_error_and_return;
+ isolate->ThrowInvalidStringLength();
return Handle<String>::null();
}
}
diff --git a/src/version.cc b/src/version.cc
index 9aa66c9..9dab767 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 25
-#define BUILD_NUMBER 21
+#define BUILD_NUMBER 22
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index 49068e7..d1c893d 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -1160,8 +1160,31 @@
DeoptimizeIf(zero, instr->environment());
}
- // TODO(svenpanne) Add correction terms.
- __ TruncatingDiv(dividend, divisor);
+ // Easy case: We need no dynamic check for the dividend and the flooring
+ // division is the same as the truncating division.
+ if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
+ __ TruncatingDiv(dividend, Abs(divisor));
+ if (divisor < 0) __ negl(rdx);
+ return;
+ }
+
+ // In the general case we may need to adjust before and after the truncating
+ // division to get a flooring division.
+ Register temp = ToRegister(instr->temp3());
+ ASSERT(!temp.is(dividend) && !temp.is(rax) && !temp.is(rdx));
+ Label needs_adjustment, done;
+ __ cmpl(dividend, Immediate(0));
+ __ j(divisor > 0 ? less : greater, &needs_adjustment, Label::kNear);
+ __ TruncatingDiv(dividend, Abs(divisor));
+ if (divisor < 0) __ negl(rdx);
+ __ jmp(&done, Label::kNear);
+ __ bind(&needs_adjustment);
+ __ leal(temp, Operand(dividend, divisor > 0 ? 1 : -1));
+ __ TruncatingDiv(temp, Abs(divisor));
+ if (divisor < 0) __ negl(rdx);
+ __ decl(rdx);
+ __ bind(&done);
}
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index aad9597..13df32c 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -1349,24 +1349,30 @@
int32_t divisor = instr->right()->GetInteger32Constant();
LOperand* temp1 = FixedTemp(rax);
LOperand* temp2 = FixedTemp(rdx);
+ LOperand* temp3 =
+ ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) ||
+ (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ?
+ NULL : TempRegister();
LInstruction* result =
DefineFixed(new(zone()) LFlooringDivByConstI(dividend,
divisor,
temp1,
- temp2),
+ temp2,
+ temp3),
rdx);
- bool can_deopt =
- divisor == 0 ||
- (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0);
- return can_deopt ? AssignEnvironment(result) : result;
+ if (divisor == 0 ||
+ (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) {
+ result = AssignEnvironment(result);
+ }
+ return result;
}
LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) {
if (instr->RightIsPowerOf2()) {
return DoFlooringDivByPowerOf2I(instr);
- } else if (false && instr->right()->IsConstant()) {
- return DoFlooringDivByConstI(instr); // TODO(svenpanne) Fix and re-enable.
+ } else if (instr->right()->IsConstant()) {
+ return DoFlooringDivByConstI(instr);
} else {
return DoDivI(instr);
}
diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
index 8ae1319..cbe7a39 100644
--- a/src/x64/lithium-x64.h
+++ b/src/x64/lithium-x64.h
@@ -759,22 +759,25 @@
};
-class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 2> {
+class LFlooringDivByConstI V8_FINAL : public LTemplateInstruction<1, 1, 3> {
public:
LFlooringDivByConstI(LOperand* dividend,
int32_t divisor,
LOperand* temp1,
- LOperand* temp2) {
+ LOperand* temp2,
+ LOperand* temp3) {
inputs_[0] = dividend;
divisor_ = divisor;
temps_[0] = temp1;
temps_[1] = temp2;
+ temps_[2] = temp3;
}
LOperand* dividend() { return inputs_[0]; }
int32_t divisor() const { return divisor_; }
LOperand* temp1() { return temps_[0]; }
- LOperand* temp2() { return temps_[0]; }
+ LOperand* temp2() { return temps_[1]; }
+ LOperand* temp3() { return temps_[2]; }
DECLARE_CONCRETE_INSTRUCTION(FlooringDivByConstI, "flooring-div-by-const-i")
DECLARE_HYDROGEN_ACCESSOR(MathFloorOfDiv)