Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc
index 36b7c5d..f14aaf6 100644
--- a/src/full-codegen/x87/full-codegen-x87.cc
+++ b/src/full-codegen/x87/full-codegen-x87.cc
@@ -285,39 +285,35 @@
__ CallRuntime(Runtime::kTraceEnter);
}
- // Visit the declarations and body unless there is an illegal
- // redeclaration.
- if (scope()->HasIllegalRedeclaration()) {
+ // Visit the declarations and body.
+ PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
+ {
Comment cmnt(masm_, "[ Declarations");
- VisitForEffect(scope()->GetIllegalRedeclaration());
+ VisitDeclarations(scope()->declarations());
+ }
- } else {
- PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
- { Comment cmnt(masm_, "[ Declarations");
- VisitDeclarations(scope()->declarations());
- }
+ // Assert that the declarations do not use ICs. Otherwise the debugger
+ // won't be able to redirect a PC at an IC to the correct IC in newly
+ // recompiled code.
+ DCHECK_EQ(0, ic_total_count_);
- // Assert that the declarations do not use ICs. Otherwise the debugger
- // won't be able to redirect a PC at an IC to the correct IC in newly
- // recompiled code.
- DCHECK_EQ(0, ic_total_count_);
+ {
+ Comment cmnt(masm_, "[ Stack check");
+ PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
+ Label ok;
+ ExternalReference stack_limit =
+ ExternalReference::address_of_stack_limit(isolate());
+ __ cmp(esp, Operand::StaticVariable(stack_limit));
+ __ j(above_equal, &ok, Label::kNear);
+ __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
+ __ bind(&ok);
+ }
- { Comment cmnt(masm_, "[ Stack check");
- PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
- Label ok;
- ExternalReference stack_limit
- = ExternalReference::address_of_stack_limit(isolate());
- __ cmp(esp, Operand::StaticVariable(stack_limit));
- __ j(above_equal, &ok, Label::kNear);
- __ call(isolate()->builtins()->StackCheck(), RelocInfo::CODE_TARGET);
- __ bind(&ok);
- }
-
- { Comment cmnt(masm_, "[ Body");
- DCHECK(loop_depth() == 0);
- VisitStatements(literal()->body());
- DCHECK(loop_depth() == 0);
- }
+ {
+ Comment cmnt(masm_, "[ Body");
+ DCHECK(loop_depth() == 0);
+ VisitStatements(literal()->body());
+ DCHECK(loop_depth() == 0);
}
// Always emit a 'return undefined' in case control fell off the end of
@@ -484,7 +480,7 @@
true,
true_label_,
false_label_);
- DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectableObject());
+ DCHECK(lit->IsNull() || lit->IsUndefined() || !lit->IsUndetectable());
if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
if (false_label_ != fall_through_) __ jmp(false_label_);
} else if (lit->IsTrue() || lit->IsJSObject()) {
@@ -592,7 +588,7 @@
Label* if_true,
Label* if_false,
Label* fall_through) {
- Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
+ Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, fall_through);
@@ -926,14 +922,14 @@
FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
- Label loop, exit;
- ForIn loop_statement(this, stmt);
- increment_loop_depth();
-
// Get the object to enumerate over.
SetExpressionAsStatementPosition(stmt->enumerable());
VisitForAccumulatorValue(stmt->enumerable());
- OperandStackDepthIncrement(ForIn::kElementCount);
+ OperandStackDepthIncrement(5);
+
+ Label loop, exit;
+ Iteration loop_statement(this, stmt);
+ increment_loop_depth();
// If the object is null or undefined, skip over the loop, otherwise convert
// it to a JS receiver. See ECMA-262 version 5, section 12.6.4.
@@ -1000,11 +996,6 @@
// We got a fixed array in register eax. Iterate through that.
__ bind(&fixed_array);
- // No need for a write barrier, we are storing a Smi in the feedback vector.
- int const vector_index = SmiFromSlot(slot)->value();
- __ EmitLoadTypeFeedbackVector(ebx);
- __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(vector_index)),
- Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate())));
__ push(Immediate(Smi::FromInt(1))); // Smi(1) undicates slow check
__ push(eax); // Array
__ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
@@ -1035,12 +1026,8 @@
__ cmp(edx, FieldOperand(ecx, HeapObject::kMapOffset));
__ j(equal, &update_each, Label::kNear);
- // We might get here from TurboFan or Crankshaft when something in the
- // for-in loop body deopts and only now notice in fullcodegen, that we
- // can now longer use the enum cache, i.e. left fast mode. So better record
- // this information here, in case we later OSR back into this loop or
- // reoptimize the whole function w/o rerunning the loop with the slow
- // mode object in fullcodegen (which would result in a deopt loop).
+ // We need to filter the key, record slow-path here.
+ int const vector_index = SmiFromSlot(slot)->value();
__ EmitLoadTypeFeedbackVector(edx);
__ mov(FieldOperand(edx, FixedArray::OffsetOfElementAt(vector_index)),
Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate())));
@@ -1081,8 +1068,7 @@
// Remove the pointers stored on the stack.
__ bind(loop_statement.break_label());
- __ add(esp, Immediate(5 * kPointerSize));
- OperandStackDepthDecrement(ForIn::kElementCount);
+ DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
@@ -1091,31 +1077,6 @@
}
-void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
- bool pretenure) {
- // Use the fast case closure allocation code that allocates in new
- // space for nested functions that don't need literals cloning. If
- // we're running with the --always-opt or the --prepare-always-opt
- // flag, we need to use the runtime function so that the new function
- // we are creating here gets a chance to have its code optimized and
- // doesn't just get a copy of the existing unoptimized code.
- if (!FLAG_always_opt &&
- !FLAG_prepare_always_opt &&
- !pretenure &&
- scope()->is_function_scope() &&
- info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(), info->language_mode(), info->kind());
- __ mov(ebx, Immediate(info));
- __ CallStub(&stub);
- } else {
- __ push(Immediate(info));
- __ CallRuntime(pretenure ? Runtime::kNewClosure_Tenured
- : Runtime::kNewClosure);
- }
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
FeedbackVectorSlot slot) {
DCHECK(NeedsHomeObject(initializer));
@@ -1546,12 +1507,6 @@
}
}
- if (expr->has_function()) {
- DCHECK(result_saved);
- __ push(Operand(esp, 0));
- __ CallRuntime(Runtime::kToFastProperties);
- }
-
if (result_saved) {
context()->PlugTOS();
} else {
@@ -1793,64 +1748,44 @@
// this. It stays on the stack while we update the iterator.
VisitForStackValue(expr->expression());
- switch (expr->yield_kind()) {
- case Yield::kSuspend:
- // Pop value from top-of-stack slot; box result into result register.
- EmitCreateIteratorResult(false);
- __ push(result_register());
- // Fall through.
- case Yield::kInitial: {
- Label suspend, continuation, post_runtime, resume;
+ Label suspend, continuation, post_runtime, resume;
- __ jmp(&suspend);
- __ bind(&continuation);
- // When we arrive here, the stack top is the resume mode and
- // result_register() holds the input value (the argument given to the
- // respective resume operation).
- __ RecordGeneratorContinuation();
- __ pop(ebx);
- __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::RETURN)));
- __ j(not_equal, &resume);
- __ push(result_register());
- EmitCreateIteratorResult(true);
- EmitUnwindAndReturn();
+ __ jmp(&suspend);
+ __ bind(&continuation);
+ // When we arrive here, the stack top is the resume mode and
+ // result_register() holds the input value (the argument given to the
+ // respective resume operation).
+ __ RecordGeneratorContinuation();
+ __ pop(ebx);
+ __ cmp(ebx, Immediate(Smi::FromInt(JSGeneratorObject::RETURN)));
+ __ j(not_equal, &resume);
+ __ push(result_register());
+ EmitCreateIteratorResult(true);
+ EmitUnwindAndReturn();
- __ bind(&suspend);
- VisitForAccumulatorValue(expr->generator_object());
- DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
- __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
- Immediate(Smi::FromInt(continuation.pos())));
- __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
- __ mov(ecx, esi);
- __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
- kDontSaveFPRegs);
- __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
- __ cmp(esp, ebx);
- __ j(equal, &post_runtime);
- __ push(eax); // generator object
- __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
- __ mov(context_register(),
- Operand(ebp, StandardFrameConstants::kContextOffset));
- __ bind(&post_runtime);
- PopOperand(result_register());
- EmitReturnSequence();
+ __ bind(&suspend);
+ OperandStackDepthIncrement(1); // Not popped on this path.
+ VisitForAccumulatorValue(expr->generator_object());
+ DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
+ __ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
+ Immediate(Smi::FromInt(continuation.pos())));
+ __ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
+ __ mov(ecx, esi);
+ __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
+ kDontSaveFPRegs);
+ __ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
+ __ cmp(esp, ebx);
+ __ j(equal, &post_runtime);
+ __ push(eax); // generator object
+ __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
+ __ mov(context_register(),
+ Operand(ebp, StandardFrameConstants::kContextOffset));
+ __ bind(&post_runtime);
+ PopOperand(result_register());
+ EmitReturnSequence();
- __ bind(&resume);
- context()->Plug(result_register());
- break;
- }
-
- case Yield::kFinal: {
- // Pop value from top-of-stack slot, box result into result register.
- OperandStackDepthDecrement(1);
- EmitCreateIteratorResult(true);
- EmitUnwindAndReturn();
- break;
- }
-
- case Yield::kDelegating:
- UNREACHABLE();
- }
+ __ bind(&resume);
+ context()->Plug(result_register());
}
@@ -1878,7 +1813,10 @@
// Push receiver.
__ push(FieldOperand(ebx, JSGeneratorObject::kReceiverOffset));
- // Push holes for arguments to generator function.
+ // Push holes for arguments to generator function. Since the parser forced
+ // context allocation for any variables in generators, the actual argument
+ // values have already been copied into the context and these dummy values
+ // will never be used.
__ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ mov(edx,
FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
@@ -1983,19 +1921,7 @@
__ mov(FieldOperand(eax, JSIteratorResult::kDoneOffset),
isolate()->factory()->ToBoolean(done));
STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
-}
-
-
-void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
- SetExpressionPosition(prop);
- Literal* key = prop->key()->AsLiteral();
- DCHECK(!key->value()->IsSmi());
- DCHECK(!prop->IsSuperAccess());
-
- __ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
- __ mov(LoadDescriptor::SlotRegister(),
- Immediate(SmiFromSlot(prop->PropertyFeedbackSlot())));
- CallLoadIC(NOT_INSIDE_TYPEOF);
+ OperandStackDepthDecrement(1);
}
@@ -2589,7 +2515,7 @@
}
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
- SetCallPosition(expr);
+ SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
if (FLAG_trace) {
__ CallRuntime(Runtime::kTraceTailCall);
@@ -2945,9 +2871,10 @@
__ CmpObjectType(eax, FIRST_JS_RECEIVER_TYPE, eax);
__ j(below, &null, Label::kNear);
- // Return 'Function' for JSFunction objects.
- __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
- __ j(equal, &function, Label::kNear);
+ // Return 'Function' for JSFunction and JSBoundFunction objects.
+ __ CmpInstanceType(eax, FIRST_FUNCTION_TYPE);
+ STATIC_ASSERT(LAST_FUNCTION_TYPE == LAST_TYPE);
+ __ j(above_equal, &function, Label::kNear);
// Check if the constructor in the map is a JS function.
__ GetMapConstructor(eax, eax, ebx);
@@ -3069,23 +2996,6 @@
}
-void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK_EQ(1, args->length());
-
- // Load the argument into eax and convert it.
- VisitForAccumulatorValue(args->at(0));
-
- // Convert the object to an integer.
- Label done_convert;
- __ JumpIfSmi(eax, &done_convert, Label::kNear);
- __ Push(eax);
- __ CallRuntime(Runtime::kToInteger);
- __ bind(&done_convert);
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
@@ -3269,6 +3179,12 @@
context()->Plug(eax);
}
+void FullCodeGenerator::EmitGetOrdinaryHasInstance(CallRuntime* expr) {
+ DCHECK_EQ(0, expr->arguments()->length());
+ __ mov(eax, NativeContextOperand());
+ __ mov(eax, ContextOperand(eax, Context::ORDINARY_HAS_INSTANCE_INDEX));
+ context()->Plug(eax);
+}
void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
DCHECK(expr->arguments()->length() == 0);
@@ -3310,10 +3226,12 @@
void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
+ // Push function.
+ __ LoadGlobalFunction(expr->context_index(), eax);
+ PushOperand(eax);
+
// Push undefined as receiver.
PushOperand(isolate()->factory()->undefined_value());
-
- __ LoadGlobalFunction(expr->context_index(), eax);
}
@@ -3327,58 +3245,9 @@
__ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
-}
-
-void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- int arg_count = args->length();
-
- if (expr->is_jsruntime()) {
- Comment cmnt(masm_, "[ CallRuntime");
- EmitLoadJSRuntimeFunction(expr);
-
- // Push the target function under the receiver.
- PushOperand(Operand(esp, 0));
- __ mov(Operand(esp, kPointerSize), eax);
-
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
-
- PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
- EmitCallJSRuntimeFunction(expr);
-
- // Restore context register.
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- context()->DropAndPlug(1, eax);
-
- } else {
- const Runtime::Function* function = expr->function();
- switch (function->function_id) {
-#define CALL_INTRINSIC_GENERATOR(Name) \
- case Runtime::kInline##Name: { \
- Comment cmnt(masm_, "[ Inline" #Name); \
- return Emit##Name(expr); \
- }
- FOR_EACH_FULL_CODE_INTRINSIC(CALL_INTRINSIC_GENERATOR)
-#undef CALL_INTRINSIC_GENERATOR
- default: {
- Comment cmnt(masm_, "[ CallRuntime for unhandled intrinsic");
- // Push the arguments ("left-to-right").
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
-
- // Call the C runtime function.
- PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
- __ CallRuntime(expr->function(), arg_count);
- OperandStackDepthDecrement(arg_count);
- context()->Plug(eax);
- }
- }
- }
+ // Restore context register.
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
}
@@ -3623,11 +3492,11 @@
__ jmp(&stub_call, Label::kNear);
__ bind(&slow);
}
- if (!is_strong(language_mode())) {
- ToNumberStub convert_stub(isolate());
- __ CallStub(&convert_stub);
- PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
- }
+
+ // Convert old value into a number.
+ ToNumberStub convert_stub(isolate());
+ __ CallStub(&convert_stub);
+ PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@@ -3667,9 +3536,6 @@
patch_site.EmitPatchInfo();
__ bind(&done);
- if (is_strong(language_mode())) {
- PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
- }
// Store the value returned in eax.
switch (assign_type) {
case VARIABLE:
@@ -3795,7 +3661,7 @@
// Check for undetectable objects => true.
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
__ test_b(FieldOperand(edx, Map::kBitFieldOffset),
- 1 << Map::kIsUndetectable);
+ Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through);
} else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(eax, if_false);
@@ -3814,7 +3680,7 @@
__ j(below, if_false);
// Check for callable or undetectable objects => false.
__ test_b(FieldOperand(edx, Map::kBitFieldOffset),
- (1 << Map::kIsCallable) | (1 << Map::kIsUndetectable));
+ Immediate((1 << Map::kIsCallable) | (1 << Map::kIsUndetectable)));
Split(zero, if_true, if_false, fall_through);
// clang-format off
#define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
@@ -3925,21 +3791,16 @@
__ cmp(eax, nil_value);
Split(equal, if_true, if_false, fall_through);
} else {
- Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
- CallIC(ic, expr->CompareOperationFeedbackId());
- __ cmp(eax, isolate()->factory()->true_value());
- Split(equal, if_true, if_false, fall_through);
+ __ JumpIfSmi(eax, if_false);
+ __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
+ __ test_b(FieldOperand(eax, Map::kBitFieldOffset),
+ Immediate(1 << Map::kIsUndetectable));
+ Split(not_zero, if_true, if_false, fall_through);
}
context()->Plug(if_true, if_false);
}
-void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
- __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
- context()->Plug(eax);
-}
-
-
Register FullCodeGenerator::result_register() {
return eax;
}
@@ -3949,6 +3810,10 @@
return esi;
}
+void FullCodeGenerator::LoadFromFrameField(int frame_offset, Register value) {
+ DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
+ __ mov(value, Operand(ebp, frame_offset));
+}
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
@@ -4015,12 +3880,6 @@
}
-void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) {
- DCHECK(!slot.IsInvalid());
- __ mov(VectorStoreICTrampolineDescriptor::SlotRegister(),
- Immediate(SmiFromSlot(slot)));
-}
-
void FullCodeGenerator::DeferredCommands::EmitCommands() {
DCHECK(!result_register().is(edx));
__ Pop(result_register()); // Restore the accumulator.
@@ -4078,7 +3937,6 @@
*jns_offset_address = kJnsOffset;
break;
case ON_STACK_REPLACEMENT:
- case OSR_AFTER_STACK_CHECK:
// sub <profiling_counter>, <delta> ;; Not changed
// nop
// nop
@@ -4116,15 +3974,10 @@
DCHECK_EQ(kNopByteOne, *jns_instr_address);
DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
- if (Assembler::target_address_at(call_target_address, unoptimized_code) ==
- isolate->builtins()->OnStackReplacement()->entry()) {
- return ON_STACK_REPLACEMENT;
- }
-
- DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
- Assembler::target_address_at(call_target_address,
- unoptimized_code));
- return OSR_AFTER_STACK_CHECK;
+ DCHECK_EQ(
+ isolate->builtins()->OnStackReplacement()->entry(),
+ Assembler::target_address_at(call_target_address, unoptimized_code));
+ return ON_STACK_REPLACEMENT;
}