summaryrefslogtreecommitdiff
path: root/deps/v8/src/full-codegen/x87/full-codegen-x87.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/full-codegen/x87/full-codegen-x87.cc')
-rw-r--r--deps/v8/src/full-codegen/x87/full-codegen-x87.cc361
1 files changed, 90 insertions, 271 deletions
diff --git a/deps/v8/src/full-codegen/x87/full-codegen-x87.cc b/deps/v8/src/full-codegen/x87/full-codegen-x87.cc
index a85152d7a9..8b1e5e98d4 100644
--- a/deps/v8/src/full-codegen/x87/full-codegen-x87.cc
+++ b/deps/v8/src/full-codegen/x87/full-codegen-x87.cc
@@ -7,7 +7,6 @@
#include "src/code-factory.h"
#include "src/code-stubs.h"
#include "src/codegen.h"
-#include "src/compiler.h"
#include "src/debug/debug.h"
#include "src/full-codegen/full-codegen.h"
#include "src/ic/ic.h"
@@ -106,24 +105,12 @@ void FullCodeGenerator::Generate() {
}
#endif
- // Sloppy mode functions and builtins need to replace the receiver with the
- // global proxy when called as functions (without an explicit receiver
- // object).
- if (info->MustReplaceUndefinedReceiverWithGlobalProxy()) {
- Label ok;
- // +1 for return address.
+ if (FLAG_debug_code && info->ExpectsJSReceiverAsReceiver()) {
int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
__ mov(ecx, Operand(esp, receiver_offset));
-
- __ cmp(ecx, isolate()->factory()->undefined_value());
- __ j(not_equal, &ok, Label::kNear);
-
- __ mov(ecx, GlobalObjectOperand());
- __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
-
- __ mov(Operand(esp, receiver_offset), ecx);
-
- __ bind(&ok);
+ __ AssertNotSmi(ecx);
+ __ CmpObjectType(ecx, FIRST_SPEC_OBJECT_TYPE, ecx);
+ __ Assert(above_equal, kSloppyFunctionExpectsJSReceiverReceiver);
}
// Open a frame scope to indicate that there is a frame on the stack. The
@@ -133,7 +120,6 @@ void FullCodeGenerator::Generate() {
info->set_prologue_offset(masm_->pc_offset());
__ Prologue(info->IsCodePreAgingActive());
- info->AddNoFrameRange(0, masm_->pc_offset());
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
@@ -187,6 +173,7 @@ void FullCodeGenerator::Generate() {
__ push(edi);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext, 2);
+ PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
} else if (slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(isolate(), slots);
__ CallStub(&stub);
@@ -228,8 +215,8 @@ void FullCodeGenerator::Generate() {
}
}
}
+ PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
- PrepareForBailoutForId(BailoutId::Prologue(), NO_REGISTERS);
// Function register is trashed in case we bailout here. But since that
// could happen only when we allocate a context the value of
// |function_in_register| is correct.
@@ -433,13 +420,11 @@ void FullCodeGenerator::EmitReturnSequence() {
__ bind(&ok);
SetReturnPosition(literal());
- int no_frame_start = masm_->pc_offset();
__ leave();
int arg_count = info_->scope()->num_parameters() + 1;
int arguments_bytes = arg_count * kPointerSize;
__ Ret(arguments_bytes, ecx);
- info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
}
}
@@ -797,16 +782,14 @@ void FullCodeGenerator::VisitVariableDeclaration(
} else {
__ push(Immediate(Smi::FromInt(0))); // Indicates no initial value.
}
- __ CallRuntime(IsImmutableVariableMode(mode)
- ? Runtime::kDeclareReadOnlyLookupSlot
- : Runtime::kDeclareLookupSlot,
- 2);
+ __ push(
+ Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes())));
+ __ CallRuntime(Runtime::kDeclareLookupSlot, 3);
break;
}
}
}
-
void FullCodeGenerator::VisitFunctionDeclaration(
FunctionDeclaration* declaration) {
VariableProxy* proxy = declaration->proxy();
@@ -848,7 +831,9 @@ void FullCodeGenerator::VisitFunctionDeclaration(
Comment cmnt(masm_, "[ FunctionDeclaration");
__ push(Immediate(variable->name()));
VisitForStackValue(declaration->fun());
- __ CallRuntime(Runtime::kDeclareLookupSlot, 2);
+ __ push(
+ Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes())));
+ __ CallRuntime(Runtime::kDeclareLookupSlot, 3);
break;
}
}
@@ -1070,7 +1055,6 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(Immediate(Smi::FromInt(0))); // Initial index.
// Generate code for doing the condition check.
- PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&loop);
SetExpressionAsStatementPosition(stmt->each());
@@ -1120,6 +1104,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
+ // Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
+ PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@@ -1168,7 +1154,7 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
- FeedbackVectorICSlot slot) {
+ FeedbackVectorSlot slot) {
DCHECK(NeedsHomeObject(initializer));
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
__ mov(StoreDescriptor::NameRegister(),
@@ -1179,8 +1165,9 @@ void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
}
-void FullCodeGenerator::EmitSetHomeObjectAccumulator(
- Expression* initializer, int offset, FeedbackVectorICSlot slot) {
+void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
+ int offset,
+ FeedbackVectorSlot slot) {
DCHECK(NeedsHomeObject(initializer));
__ mov(StoreDescriptor::ReceiverRegister(), eax);
__ mov(StoreDescriptor::NameRegister(),
@@ -1311,27 +1298,11 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
Variable* var = proxy->var();
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
- if (var->IsGlobalSlot()) {
- DCHECK(var->index() > 0);
- DCHECK(var->IsStaticGlobalObjectProperty());
- int const slot = var->index();
- int const depth = scope()->ContextChainLength(var->scope());
- if (depth <= LoadGlobalViaContextStub::kMaximumDepth) {
- __ Move(LoadGlobalViaContextDescriptor::SlotRegister(), Immediate(slot));
- LoadGlobalViaContextStub stub(isolate(), depth);
- __ CallStub(&stub);
- } else {
- __ Push(Smi::FromInt(slot));
- __ CallRuntime(Runtime::kLoadGlobalViaContext, 1);
- }
-
- } else {
- __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
- __ mov(LoadDescriptor::NameRegister(), var->name());
- __ mov(LoadDescriptor::SlotRegister(),
- Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
- CallLoadIC(typeof_mode);
- }
+ __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadDescriptor::NameRegister(), var->name());
+ __ mov(LoadDescriptor::SlotRegister(),
+ Immediate(SmiFromSlot(proxy->VariableFeedbackSlot())));
+ CallLoadIC(typeof_mode);
}
@@ -1671,7 +1642,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Comment cmnt(masm_, "[ ArrayLiteral");
- expr->BuildConstantElements(isolate());
Handle<FixedArray> constant_elements = expr->constant_elements();
bool has_constant_fast_elements =
IsFastObjectElementsKind(expr->constant_elements_kind());
@@ -1722,7 +1692,15 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
}
VisitForAccumulatorValue(subexpr);
- if (has_constant_fast_elements) {
+ if (FLAG_vector_stores) {
+ __ mov(StoreDescriptor::NameRegister(),
+ Immediate(Smi::FromInt(array_index)));
+ __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
+ EmitLoadStoreICSlot(expr->LiteralFeedbackSlot());
+ Handle<Code> ic =
+ CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
+ CallIC(ic);
+ } else if (has_constant_fast_elements) {
// Fast-case array literal with ElementsKind of FAST_*_ELEMENTS, they
// cannot transition and don't need to call the runtime stub.
int offset = FixedArray::kHeaderSize + (array_index * kPointerSize);
@@ -1739,7 +1717,6 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
StoreArrayLiteralElementStub stub(isolate());
__ CallStub(&stub);
}
-
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
@@ -2051,8 +2028,10 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ mov(edi, eax);
__ mov(Operand(esp, 2 * kPointerSize), edi);
SetCallPosition(expr, 1);
- CallFunctionStub stub(isolate(), 1, CALL_AS_METHOD);
- __ CallStub(&stub);
+ __ Set(eax, 1);
+ __ Call(
+ isolate()->builtins()->Call(ConvertReceiverMode::kNotNullOrUndefined),
+ RelocInfo::CODE_TARGET);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ Drop(1); // The function is still on the stack; drop it.
@@ -2181,7 +2160,7 @@ void FullCodeGenerator::EmitCreateIteratorResult(bool done) {
__ bind(&done_allocate);
__ mov(ebx, GlobalObjectOperand());
- __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
+ __ mov(ebx, FieldOperand(ebx, JSGlobalObject::kNativeContextOffset));
__ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
__ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
__ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
@@ -2408,7 +2387,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
void FullCodeGenerator::EmitAssignment(Expression* expr,
- FeedbackVectorICSlot slot) {
+ FeedbackVectorSlot slot) {
DCHECK(expr->IsValidReferenceExpressionOrThis());
Property* prop = expr->AsProperty();
@@ -2499,7 +2478,7 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
- FeedbackVectorICSlot slot) {
+ FeedbackVectorSlot slot) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ mov(StoreDescriptor::NameRegister(), var->name());
@@ -2507,26 +2486,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
CallStoreIC();
- } else if (var->IsGlobalSlot()) {
- // Global var, const, or let.
- DCHECK(var->index() > 0);
- DCHECK(var->IsStaticGlobalObjectProperty());
- int const slot = var->index();
- int const depth = scope()->ContextChainLength(var->scope());
- if (depth <= StoreGlobalViaContextStub::kMaximumDepth) {
- __ Move(StoreGlobalViaContextDescriptor::SlotRegister(), Immediate(slot));
- DCHECK(StoreGlobalViaContextDescriptor::ValueRegister().is(eax));
- StoreGlobalViaContextStub stub(isolate(), depth, language_mode());
- __ CallStub(&stub);
- } else {
- __ Push(Smi::FromInt(slot));
- __ Push(eax);
- __ CallRuntime(is_strict(language_mode())
- ? Runtime::kStoreGlobalViaContext_Strict
- : Runtime::kStoreGlobalViaContext_Sloppy,
- 2);
- }
-
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
DCHECK(!var->IsLookupSlot());
@@ -2741,10 +2700,9 @@ void FullCodeGenerator::CallIC(Handle<Code> code,
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();
- CallICState::CallType call_type =
- callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
// Get the target function.
- if (call_type == CallICState::FUNCTION) {
+ ConvertReceiverMode convert_mode;
+ if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, NO_REGISTERS);
@@ -2752,6 +2710,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
__ push(Immediate(isolate()->factory()->undefined_value()));
+ convert_mode = ConvertReceiverMode::kNullOrUndefined;
} else {
// Load the function from the receiver.
DCHECK(callee->IsProperty());
@@ -2762,9 +2721,10 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
// Push the target function under the receiver.
__ push(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
+ convert_mode = ConvertReceiverMode::kNotNullOrUndefined;
}
- EmitCall(expr, call_type);
+ EmitCall(expr, convert_mode);
}
@@ -2801,7 +2761,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// Stack here:
// - target function
// - this (receiver)
- EmitCall(expr, CallICState::METHOD);
+ EmitCall(expr);
}
@@ -2824,7 +2784,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ push(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
- EmitCall(expr, CallICState::METHOD);
+ EmitCall(expr, ConvertReceiverMode::kNotNullOrUndefined);
}
@@ -2859,11 +2819,11 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// Stack here:
// - target function
// - this (receiver)
- EmitCall(expr, CallICState::METHOD);
+ EmitCall(expr);
}
-void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
+void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
// Load the arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
@@ -2871,8 +2831,9 @@ void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
VisitForStackValue(args->at(i));
}
+ PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
SetCallPosition(expr, arg_count);
- Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, call_type).code();
+ Handle<Code> ic = CodeFactory::CallIC(isolate(), arg_count, mode).code();
__ Move(edx, Immediate(SmiFromSlot(expr->CallFeedbackICSlot())));
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
// Don't assign a type feedback id to the IC, since type feedback is provided
@@ -2951,88 +2912,38 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
}
-void FullCodeGenerator::VisitCall(Call* expr) {
-#ifdef DEBUG
- // We want to verify that RecordJSReturnSite gets called on all paths
- // through this function. Avoid early returns.
- expr->return_is_recorded_ = false;
-#endif
-
- Comment cmnt(masm_, "[ Call");
- Expression* callee = expr->expression();
- Call::CallType call_type = expr->GetCallType(isolate());
-
- if (call_type == Call::POSSIBLY_EVAL_CALL) {
- // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
- // to resolve the function we need to call. Then we call the resolved
- // function using the given arguments.
- ZoneList<Expression*>* args = expr->arguments();
- int arg_count = args->length();
-
- PushCalleeAndWithBaseObject(expr);
-
- // Push the arguments.
- for (int i = 0; i < arg_count; i++) {
- VisitForStackValue(args->at(i));
- }
+void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
+ // In a call to eval, we first call RuntimeHidden_ResolvePossiblyDirectEval
+ // to resolve the function we need to call. Then we call the resolved
+ // function using the given arguments.
+ ZoneList<Expression*>* args = expr->arguments();
+ int arg_count = args->length();
- // Push a copy of the function (found below the arguments) and
- // resolve eval.
- __ push(Operand(esp, (arg_count + 1) * kPointerSize));
- EmitResolvePossiblyDirectEval(arg_count);
+ PushCalleeAndWithBaseObject(expr);
- // Touch up the stack with the resolved function.
- __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
+ // Push the arguments.
+ for (int i = 0; i < arg_count; i++) {
+ VisitForStackValue(args->at(i));
+ }
- PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
+ // Push a copy of the function (found below the arguments) and
+ // resolve eval.
+ __ push(Operand(esp, (arg_count + 1) * kPointerSize));
+ EmitResolvePossiblyDirectEval(arg_count);
- SetCallPosition(expr, arg_count);
- CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
- __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
- __ CallStub(&stub);
- RecordJSReturnSite(expr);
- // Restore context register.
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- context()->DropAndPlug(1, eax);
+ // Touch up the stack with the resolved function.
+ __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
- } else if (call_type == Call::GLOBAL_CALL) {
- EmitCallWithLoadIC(expr);
- } else if (call_type == Call::LOOKUP_SLOT_CALL) {
- // Call to a lookup slot (dynamically introduced variable).
- PushCalleeAndWithBaseObject(expr);
- EmitCall(expr);
- } else if (call_type == Call::PROPERTY_CALL) {
- Property* property = callee->AsProperty();
- bool is_named_call = property->key()->IsPropertyName();
- if (property->IsSuperAccess()) {
- if (is_named_call) {
- EmitSuperCallWithLoadIC(expr);
- } else {
- EmitKeyedSuperCallWithLoadIC(expr);
- }
- } else {
- VisitForStackValue(property->obj());
- if (is_named_call) {
- EmitCallWithLoadIC(expr);
- } else {
- EmitKeyedCallWithLoadIC(expr, property->key());
- }
- }
- } else if (call_type == Call::SUPER_CALL) {
- EmitSuperConstructorCall(expr);
- } else {
- DCHECK(call_type == Call::OTHER_CALL);
- // Call to an arbitrary expression not handled specially above.
- VisitForStackValue(callee);
- __ push(Immediate(isolate()->factory()->undefined_value()));
- // Emit function call.
- EmitCall(expr);
- }
+ PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
-#ifdef DEBUG
- // RecordJSReturnSite should have been called.
- DCHECK(expr->return_is_recorded_);
-#endif
+ SetCallPosition(expr, arg_count);
+ __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
+ __ Set(eax, arg_count);
+ __ Call(isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
+ RecordJSReturnSite(expr);
+ // Restore context register.
+ __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+ context()->DropAndPlug(1, eax);
}
@@ -3671,32 +3582,6 @@ void FullCodeGenerator::EmitToInteger(CallRuntime* expr) {
}
-void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK_EQ(args->length(), 1);
-
- // Load the argument into eax and call the stub.
- VisitForAccumulatorValue(args->at(0));
-
- NumberToStringStub stub(isolate());
- __ CallStub(&stub);
- context()->Plug(eax);
-}
-
-
-void FullCodeGenerator::EmitToString(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK_EQ(1, args->length());
-
- // Load the argument into eax and convert it.
- VisitForAccumulatorValue(args->at(0));
-
- ToStringStub stub(isolate());
- __ CallStub(&stub);
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitToName(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_EQ(1, args->length());
@@ -3718,19 +3603,6 @@ void FullCodeGenerator::EmitToName(CallRuntime* expr) {
}
-void FullCodeGenerator::EmitToObject(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK_EQ(1, args->length());
-
- // Load the argument into eax and convert it.
- VisitForAccumulatorValue(args->at(0));
-
- ToObjectStub stub(isolate());
- __ CallStub(&stub);
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
@@ -3844,19 +3716,6 @@ void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
}
-void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK_EQ(2, args->length());
- VisitForStackValue(args->at(0));
- VisitForAccumulatorValue(args->at(1));
-
- __ pop(edx);
- StringAddStub stub(isolate(), STRING_ADD_CHECK_BOTH, NOT_TENURED);
- __ CallStub(&stub);
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitCall(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK_LE(2, args->length());
@@ -3864,6 +3723,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
+ PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to edi.
int const argc = args->length() - 2;
__ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
@@ -3877,38 +3737,6 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
}
-void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() >= 2);
-
- int arg_count = args->length() - 2; // 2 ~ receiver and function.
- for (int i = 0; i < arg_count + 1; ++i) {
- VisitForStackValue(args->at(i));
- }
- VisitForAccumulatorValue(args->last()); // Function.
-
- Label runtime, done;
- // Check for non-function argument (including proxy).
- __ JumpIfSmi(eax, &runtime);
- __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
- __ j(not_equal, &runtime);
-
- // InvokeFunction requires the function in edi. Move it in there.
- __ mov(edi, result_register());
- ParameterCount count(arg_count);
- __ InvokeFunction(edi, count, CALL_FUNCTION, NullCallWrapper());
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
- __ jmp(&done);
-
- __ bind(&runtime);
- __ push(eax);
- __ CallRuntime(Runtime::kCallFunction, args->length());
- __ bind(&done);
-
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 2);
@@ -3957,21 +3785,6 @@ void FullCodeGenerator::EmitDefaultConstructorCallSuper(CallRuntime* expr) {
}
-void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
- // Load the arguments on the stack and call the stub.
- RegExpConstructResultStub stub(isolate());
- ZoneList<Expression*>* args = expr->arguments();
- DCHECK(args->length() == 3);
- VisitForStackValue(args->at(0));
- VisitForStackValue(args->at(1));
- VisitForAccumulatorValue(args->at(2));
- __ pop(ebx);
- __ pop(ecx);
- __ CallStub(&stub);
- context()->Plug(eax);
-}
-
-
void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 1);
@@ -4136,6 +3949,11 @@ void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
__ j(overflow, &bailout);
__ shr(string_length, 1);
+
+ // Bailout for large object allocations.
+ __ cmp(string_length, Page::kMaxRegularHeapObjectSize);
+ __ j(greater, &bailout);
+
// Live registers and stack values:
// string_length
// elements
@@ -4294,7 +4112,7 @@ void FullCodeGenerator::EmitCreateIterResultObject(CallRuntime* expr) {
__ Allocate(JSIteratorResult::kSize, eax, ecx, edx, &runtime, TAG_OBJECT);
__ mov(ebx, GlobalObjectOperand());
- __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
+ __ mov(ebx, FieldOperand(ebx, JSGlobalObject::kNativeContextOffset));
__ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
__ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
__ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
@@ -4319,7 +4137,7 @@ void FullCodeGenerator::EmitLoadJSRuntimeFunction(CallRuntime* expr) {
__ push(Immediate(isolate()->factory()->undefined_value()));
__ mov(eax, GlobalObjectOperand());
- __ mov(eax, FieldOperand(eax, GlobalObject::kNativeContextOffset));
+ __ mov(eax, FieldOperand(eax, JSGlobalObject::kNativeContextOffset));
__ mov(eax, ContextOperand(eax, expr->context_index()));
}
@@ -4329,9 +4147,10 @@ void FullCodeGenerator::EmitCallJSRuntimeFunction(CallRuntime* expr) {
int arg_count = args->length();
SetCallPosition(expr, arg_count);
- CallFunctionStub stub(isolate(), arg_count, NO_CALL_FUNCTION_FLAGS);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
- __ CallStub(&stub);
+ __ Set(eax, arg_count);
+ __ Call(isolate()->builtins()->Call(ConvertReceiverMode::kNullOrUndefined),
+ RelocInfo::CODE_TARGET);
}
@@ -4940,8 +4759,8 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
} else {
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
CallIC(ic, expr->CompareOperationFeedbackId());
- __ test(eax, eax);
- Split(not_zero, if_true, if_false, fall_through);
+ __ cmp(eax, isolate()->factory()->true_value());
+ Split(equal, if_true, if_false, fall_through);
}
context()->Plug(if_true, if_false);
}
@@ -5049,7 +4868,7 @@ void FullCodeGenerator::ClearPendingMessage() {
}
-void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorICSlot slot) {
+void FullCodeGenerator::EmitLoadStoreICSlot(FeedbackVectorSlot slot) {
DCHECK(FLAG_vector_stores && !slot.IsInvalid());
__ mov(VectorStoreICTrampolineDescriptor::SlotRegister(),
Immediate(SmiFromSlot(slot)));