diff options
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.cc | 361 |
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))); |