Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/crankshaft/arm64/lithium-codegen-arm64.cc b/src/crankshaft/arm64/lithium-codegen-arm64.cc
index 6399a8b..9bbc8b8 100644
--- a/src/crankshaft/arm64/lithium-codegen-arm64.cc
+++ b/src/crankshaft/arm64/lithium-codegen-arm64.cc
@@ -359,38 +359,6 @@
}
-void LCodeGen::DoCallFunction(LCallFunction* instr) {
- HCallFunction* hinstr = instr->hydrogen();
- DCHECK(ToRegister(instr->context()).is(cp));
- DCHECK(ToRegister(instr->function()).Is(x1));
- DCHECK(ToRegister(instr->result()).Is(x0));
-
- int arity = instr->arity();
- ConvertReceiverMode mode = hinstr->convert_mode();
- if (hinstr->HasVectorAndSlot()) {
- Register slot_register = ToRegister(instr->temp_slot());
- Register vector_register = ToRegister(instr->temp_vector());
- DCHECK(slot_register.is(x3));
- DCHECK(vector_register.is(x2));
-
- AllowDeferredHandleDereference vector_structure_check;
- Handle<TypeFeedbackVector> vector = hinstr->feedback_vector();
- int index = vector->GetIndex(hinstr->slot());
-
- __ Mov(vector_register, vector);
- __ Mov(slot_register, Operand(Smi::FromInt(index)));
-
- Handle<Code> ic =
- CodeFactory::CallICInOptimizedCode(isolate(), arity, mode).code();
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
- } else {
- __ Mov(x0, arity);
- CallCode(isolate()->builtins()->Call(mode), RelocInfo::CODE_TARGET, instr);
- }
- RecordPushedArgumentsDelta(hinstr->argument_delta());
-}
-
-
void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
DCHECK(instr->IsMarkedAsCall());
DCHECK(ToRegister(instr->context()).is(cp));
@@ -606,19 +574,20 @@
info()->set_prologue_offset(masm_->pc_offset());
if (NeedsEagerFrame()) {
if (info()->IsStub()) {
- __ StubPrologue();
+ __ StubPrologue(
+ StackFrame::STUB,
+ GetStackSlotCount() + TypedFrameConstants::kFixedSlotCount);
} else {
__ Prologue(info()->GeneratePreagedPrologue());
+ // Reserve space for the stack slots needed by the code.
+ int slots = GetStackSlotCount();
+ if (slots > 0) {
+ __ Claim(slots, kPointerSize);
+ }
}
frame_is_built_ = true;
}
- // Reserve space for the stack slots needed by the code.
- int slots = GetStackSlotCount();
- if (slots > 0) {
- __ Claim(slots, kPointerSize);
- }
-
if (info()->saves_caller_doubles()) {
SaveCallerDoubles();
}
@@ -740,11 +709,11 @@
DCHECK(!frame_is_built_);
DCHECK(info()->IsStub());
frame_is_built_ = true;
- __ Push(lr, fp, cp);
+ __ Push(lr, fp);
__ Mov(fp, Smi::FromInt(StackFrame::STUB));
__ Push(fp);
__ Add(fp, __ StackPointer(),
- StandardFrameConstants::kFixedFrameSizeFromFp);
+ TypedFrameConstants::kFixedFrameSizeFromFp);
Comment(";;; Deferred code");
}
@@ -753,7 +722,7 @@
if (NeedsDeferredFrame()) {
Comment(";;; Destroy frame");
DCHECK(frame_is_built_);
- __ Pop(xzr, cp, fp, lr);
+ __ Pop(xzr, fp, lr);
frame_is_built_ = false;
}
@@ -1560,14 +1529,26 @@
__ B(ne, &loop);
__ Bind(&invoke);
+
+ InvokeFlag flag = CALL_FUNCTION;
+ if (instr->hydrogen()->tail_call_mode() == TailCallMode::kAllow) {
+ DCHECK(!info()->saves_caller_doubles());
+ // TODO(ishell): drop current frame before pushing arguments to the stack.
+ flag = JUMP_FUNCTION;
+ ParameterCount actual(x0);
+ // It is safe to use x3, x4 and x5 as scratch registers here given that
+ // 1) we are not going to return to caller function anyway,
+ // 2) x3 (new.target) will be initialized below.
+ PrepareForTailCall(actual, x3, x4, x5);
+ }
+
DCHECK(instr->HasPointerMap());
LPointerMap* pointers = instr->pointer_map();
SafepointGenerator safepoint_generator(this, pointers, Safepoint::kLazyDeopt);
// The number of arguments is stored in argc (receiver) which is x0, as
// expected by InvokeFunction.
ParameterCount actual(argc);
- __ InvokeFunction(function, no_reg, actual, CALL_FUNCTION,
- safepoint_generator);
+ __ InvokeFunction(function, no_reg, actual, flag, safepoint_generator);
}
@@ -1585,16 +1566,18 @@
// get a pointer which will work well with LAccessArgumentsAt.
DCHECK(masm()->StackPointer().Is(jssp));
__ Sub(result, jssp, 2 * kPointerSize);
- } else {
+ } else if (instr->hydrogen()->arguments_adaptor()) {
DCHECK(instr->temp() != NULL);
Register previous_fp = ToRegister(instr->temp());
__ Ldr(previous_fp,
MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
- __ Ldr(result,
- MemOperand(previous_fp, StandardFrameConstants::kContextOffset));
+ __ Ldr(result, MemOperand(previous_fp,
+ CommonFrameConstants::kContextOrFrameTypeOffset));
__ Cmp(result, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
__ Csel(result, fp, previous_fp, ne);
+ } else {
+ __ Mov(result, fp);
}
}
@@ -1763,17 +1746,18 @@
__ Ldr(temp, FieldMemOperand(value, String::kLengthOffset));
EmitCompareAndBranch(instr, ne, temp, 0);
} else {
- ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
+ ToBooleanICStub::Types expected =
+ instr->hydrogen()->expected_input_types();
// Avoid deopts in the case where we've never executed this path before.
- if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
+ if (expected.IsEmpty()) expected = ToBooleanICStub::Types::Generic();
- if (expected.Contains(ToBooleanStub::UNDEFINED)) {
+ if (expected.Contains(ToBooleanICStub::UNDEFINED)) {
// undefined -> false.
__ JumpIfRoot(
value, Heap::kUndefinedValueRootIndex, false_label);
}
- if (expected.Contains(ToBooleanStub::BOOLEAN)) {
+ if (expected.Contains(ToBooleanICStub::BOOLEAN)) {
// Boolean -> its value.
__ JumpIfRoot(
value, Heap::kTrueValueRootIndex, true_label);
@@ -1781,13 +1765,13 @@
value, Heap::kFalseValueRootIndex, false_label);
}
- if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
+ if (expected.Contains(ToBooleanICStub::NULL_TYPE)) {
// 'null' -> false.
__ JumpIfRoot(
value, Heap::kNullValueRootIndex, false_label);
}
- if (expected.Contains(ToBooleanStub::SMI)) {
+ if (expected.Contains(ToBooleanICStub::SMI)) {
// Smis: 0 -> false, all other -> true.
DCHECK(Smi::FromInt(0) == 0);
__ Cbz(value, false_label);
@@ -1815,13 +1799,13 @@
}
}
- if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) {
+ if (expected.Contains(ToBooleanICStub::SPEC_OBJECT)) {
// spec object -> true.
__ CompareInstanceType(map, scratch, FIRST_JS_RECEIVER_TYPE);
__ B(ge, true_label);
}
- if (expected.Contains(ToBooleanStub::STRING)) {
+ if (expected.Contains(ToBooleanICStub::STRING)) {
// String value -> false iff empty.
Label not_string;
__ CompareInstanceType(map, scratch, FIRST_NONSTRING_TYPE);
@@ -1832,19 +1816,19 @@
__ Bind(¬_string);
}
- if (expected.Contains(ToBooleanStub::SYMBOL)) {
+ if (expected.Contains(ToBooleanICStub::SYMBOL)) {
// Symbol value -> true.
__ CompareInstanceType(map, scratch, SYMBOL_TYPE);
__ B(eq, true_label);
}
- if (expected.Contains(ToBooleanStub::SIMD_VALUE)) {
+ if (expected.Contains(ToBooleanICStub::SIMD_VALUE)) {
// SIMD value -> true.
__ CompareInstanceType(map, scratch, SIMD128_VALUE_TYPE);
__ B(eq, true_label);
}
- if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
+ if (expected.Contains(ToBooleanICStub::HEAP_NUMBER)) {
Label not_heap_number;
__ JumpIfNotRoot(map, Heap::kHeapNumberMapRootIndex, ¬_heap_number);
@@ -1867,10 +1851,9 @@
}
}
-
void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
int formal_parameter_count, int arity,
- LInstruction* instr) {
+ bool is_tail_call, LInstruction* instr) {
bool dont_adapt_arguments =
formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel;
bool can_invoke_directly =
@@ -1898,21 +1881,38 @@
__ LoadRoot(x3, Heap::kUndefinedValueRootIndex);
__ Mov(arity_reg, arity);
- // Invoke function.
- __ Ldr(x10, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
- __ Call(x10);
+ bool is_self_call = function.is_identical_to(info()->closure());
- // Set up deoptimization.
- RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
+ // Invoke function.
+ if (is_self_call) {
+ Handle<Code> self(reinterpret_cast<Code**>(__ CodeObject().location()));
+ if (is_tail_call) {
+ __ Jump(self, RelocInfo::CODE_TARGET);
+ } else {
+ __ Call(self, RelocInfo::CODE_TARGET);
+ }
+ } else {
+ __ Ldr(x10, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
+ if (is_tail_call) {
+ __ Jump(x10);
+ } else {
+ __ Call(x10);
+ }
+ }
+
+ if (!is_tail_call) {
+ // Set up deoptimization.
+ RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
+ }
} else {
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
- ParameterCount count(arity);
+ ParameterCount actual(arity);
ParameterCount expected(formal_parameter_count);
- __ InvokeFunction(function_reg, expected, count, CALL_FUNCTION, generator);
+ InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
+ __ InvokeFunction(function_reg, expected, actual, flag, generator);
}
}
-
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
DCHECK(instr->IsMarkedAsCall());
DCHECK(ToRegister(instr->result()).Is(x0));
@@ -1959,26 +1959,6 @@
}
-void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
- DCHECK(instr->IsMarkedAsCall());
- DCHECK(ToRegister(instr->function()).is(x1));
-
- // Change context.
- __ Ldr(cp, FieldMemOperand(x1, JSFunction::kContextOffset));
-
- // Always initialize new target and number of actual arguments.
- __ LoadRoot(x3, Heap::kUndefinedValueRootIndex);
- __ Mov(x0, instr->arity());
-
- // Load the code entry address
- __ Ldr(x10, FieldMemOperand(x1, JSFunction::kCodeEntryOffset));
- __ Call(x10);
-
- RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
- RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
-}
-
-
void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
CallRuntime(instr->function(), instr->arity(), instr);
RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
@@ -2225,11 +2205,12 @@
__ JumpIfSmi(input, false_label);
Register map = scratch2;
- __ CompareObjectType(input, map, scratch1, JS_FUNCTION_TYPE);
+ __ CompareObjectType(input, map, scratch1, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
if (String::Equals(isolate()->factory()->Function_string(), class_name)) {
- __ B(eq, true_label);
+ __ B(hs, true_label);
} else {
- __ B(eq, false_label);
+ __ B(hs, false_label);
}
// Check if the constructor in the map is a function.
@@ -2837,23 +2818,79 @@
__ Scvtf(result, value);
}
+void LCodeGen::PrepareForTailCall(const ParameterCount& actual,
+ Register scratch1, Register scratch2,
+ Register scratch3) {
+#if DEBUG
+ if (actual.is_reg()) {
+ DCHECK(!AreAliased(actual.reg(), scratch1, scratch2, scratch3));
+ } else {
+ DCHECK(!AreAliased(scratch1, scratch2, scratch3));
+ }
+#endif
+ if (FLAG_code_comments) {
+ if (actual.is_reg()) {
+ Comment(";;; PrepareForTailCall, actual: %s {", actual.reg().ToString());
+ } else {
+ Comment(";;; PrepareForTailCall, actual: %d {", actual.immediate());
+ }
+ }
+
+ // Check if next frame is an arguments adaptor frame.
+ Register caller_args_count_reg = scratch1;
+ Label no_arguments_adaptor, formal_parameter_count_loaded;
+ __ Ldr(scratch2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
+ __ Ldr(scratch3,
+ MemOperand(scratch2, StandardFrameConstants::kContextOffset));
+ __ Cmp(scratch3, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
+ __ B(ne, &no_arguments_adaptor);
+
+ // Drop current frame and load arguments count from arguments adaptor frame.
+ __ mov(fp, scratch2);
+ __ Ldr(caller_args_count_reg,
+ MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiUntag(caller_args_count_reg);
+ __ B(&formal_parameter_count_loaded);
+
+ __ bind(&no_arguments_adaptor);
+ // Load caller's formal parameter count
+ __ Mov(caller_args_count_reg,
+ Immediate(info()->literal()->parameter_count()));
+
+ __ bind(&formal_parameter_count_loaded);
+ __ PrepareForTailCall(actual, caller_args_count_reg, scratch2, scratch3);
+
+ Comment(";;; }");
+}
void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
+ HInvokeFunction* hinstr = instr->hydrogen();
DCHECK(ToRegister(instr->context()).is(cp));
// The function is required to be in x1.
DCHECK(ToRegister(instr->function()).is(x1));
DCHECK(instr->HasPointerMap());
- Handle<JSFunction> known_function = instr->hydrogen()->known_function();
+ bool is_tail_call = hinstr->tail_call_mode() == TailCallMode::kAllow;
+
+ if (is_tail_call) {
+ DCHECK(!info()->saves_caller_doubles());
+ ParameterCount actual(instr->arity());
+ // It is safe to use x3, x4 and x5 as scratch registers here given that
+ // 1) we are not going to return to caller function anyway,
+ // 2) x3 (new.target) will be initialized below.
+ PrepareForTailCall(actual, x3, x4, x5);
+ }
+
+ Handle<JSFunction> known_function = hinstr->known_function();
if (known_function.is_null()) {
LPointerMap* pointers = instr->pointer_map();
SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
- ParameterCount count(instr->arity());
- __ InvokeFunction(x1, no_reg, count, CALL_FUNCTION, generator);
+ ParameterCount actual(instr->arity());
+ InvokeFlag flag = is_tail_call ? JUMP_FUNCTION : CALL_FUNCTION;
+ __ InvokeFunction(x1, no_reg, actual, flag, generator);
} else {
- CallKnownFunction(known_function,
- instr->hydrogen()->formal_parameter_count(),
- instr->arity(), instr);
+ CallKnownFunction(known_function, hinstr->formal_parameter_count(),
+ instr->arity(), is_tail_call, instr);
}
RecordPushedArgumentsDelta(instr->hydrogen()->argument_delta());
}
@@ -5244,10 +5281,10 @@
DCHECK(ToRegister(instr->left()).is(x1));
DCHECK(ToRegister(instr->right()).is(x0));
- Handle<Code> code = CodeFactory::StringCompare(isolate()).code();
+ Handle<Code> code = CodeFactory::StringCompare(isolate(), instr->op()).code();
CallCode(code, RelocInfo::CODE_TARGET, instr);
-
- EmitCompareAndBranch(instr, TokenToCondition(instr->op(), false), x0, 0);
+ __ CompareRoot(x0, Heap::kTrueValueRootIndex);
+ EmitBranch(instr, eq);
}
@@ -5374,14 +5411,6 @@
}
-void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
- DCHECK(ToRegister(instr->value()).Is(x0));
- DCHECK(ToRegister(instr->result()).Is(x0));
- __ Push(x0);
- CallRuntime(Runtime::kToFastProperties, 1, instr);
-}
-
-
void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
Register object = ToRegister(instr->object());
@@ -5702,12 +5731,5 @@
__ Bind(&done);
}
-
-void LCodeGen::DoStoreFrameContext(LStoreFrameContext* instr) {
- Register context = ToRegister(instr->context());
- __ Str(context, MemOperand(fp, StandardFrameConstants::kContextOffset));
-}
-
-
} // namespace internal
} // namespace v8