diff options
Diffstat (limited to 'deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc')
-rw-r--r-- | deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc | 176 |
1 files changed, 48 insertions, 128 deletions
diff --git a/deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc b/deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc index 3571948216..e5f66cd1d4 100644 --- a/deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc @@ -4,15 +4,17 @@ #if V8_TARGET_ARCH_IA32 +#include "src/full-codegen/full-codegen.h" +#include "src/ast/compile-time-value.h" #include "src/ast/scopes.h" #include "src/code-factory.h" #include "src/code-stubs.h" #include "src/codegen.h" +#include "src/compilation-info.h" +#include "src/compiler.h" #include "src/debug/debug.h" -#include "src/full-codegen/full-codegen.h" #include "src/ia32/frames-ia32.h" #include "src/ic/ic.h" -#include "src/parsing/parser.h" namespace v8 { namespace internal { @@ -115,6 +117,17 @@ void FullCodeGenerator::Generate() { info->set_prologue_offset(masm_->pc_offset()); __ Prologue(info->GeneratePreagedPrologue()); + // Increment invocation count for the function. + { + Comment cmnt(masm_, "[ Increment invocation count"); + __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); + __ mov(ecx, FieldOperand(ecx, LiteralsArray::kFeedbackVectorOffset)); + __ add(FieldOperand( + ecx, TypeFeedbackVector::kInvocationCountIndex * kPointerSize + + TypeFeedbackVector::kHeaderSize), + Immediate(Smi::FromInt(1))); + } + { Comment cmnt(masm_, "[ Allocate locals"); int locals_count = info->scope()->num_stack_slots(); // Generators allocate locals, if any, in context slots. @@ -159,14 +172,14 @@ void FullCodeGenerator::Generate() { bool function_in_register = true; // Possibly allocate a local context. - if (info->scope()->num_heap_slots() > 0) { + if (info->scope()->NeedsContext()) { Comment cmnt(masm_, "[ Allocate context"); bool need_write_barrier = true; int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; // Argument to NewContext is the function, which is still in edi. if (info->scope()->is_script_scope()) { __ push(edi); - __ Push(info->scope()->GetScopeInfo(info->isolate())); + __ Push(info->scope()->scope_info()); __ CallRuntime(Runtime::kNewScriptContext); PrepareForBailoutForId(BailoutId::ScriptContext(), BailoutState::TOS_REGISTER); @@ -254,9 +267,8 @@ void FullCodeGenerator::Generate() { } // Possibly allocate RestParameters - int rest_index; - Variable* rest_param = info->scope()->rest_parameter(&rest_index); - if (rest_param) { + Variable* rest_param = info->scope()->rest_parameter(); + if (rest_param != nullptr) { Comment cmnt(masm_, "[ Allocate rest parameter array"); if (!function_in_register) { __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); @@ -717,7 +729,6 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); switch (variable->location()) { - case VariableLocation::GLOBAL: case VariableLocation::UNALLOCATED: { DCHECK(!variable->binding_needs_init()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); @@ -767,7 +778,6 @@ void FullCodeGenerator::VisitFunctionDeclaration( VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); switch (variable->location()) { - case VariableLocation::GLOBAL: case VariableLocation::UNALLOCATED: { FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -1066,6 +1076,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { // Generate code for going to the next element by incrementing the // index (smi) stored on top of the stack. __ bind(loop_statement.continue_label()); + PrepareForBailoutForId(stmt->IncrementId(), BailoutState::NO_REGISTERS); __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); EmitBackEdgeBookkeeping(stmt, &loop); @@ -1086,11 +1097,8 @@ void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset, FeedbackVectorSlot slot) { DCHECK(NeedsHomeObject(initializer)); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); - __ mov(StoreDescriptor::NameRegister(), - Immediate(isolate()->factory()->home_object_symbol())); __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); - EmitLoadStoreICSlot(slot); - CallStoreIC(); + CallStoreIC(slot, isolate()->factory()->home_object_symbol()); } @@ -1099,11 +1107,8 @@ void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer, FeedbackVectorSlot slot) { DCHECK(NeedsHomeObject(initializer)); __ mov(StoreDescriptor::ReceiverRegister(), eax); - __ mov(StoreDescriptor::NameRegister(), - Immediate(isolate()->factory()->home_object_symbol())); __ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize)); - EmitLoadStoreICSlot(slot); - CallStoreIC(); + CallStoreIC(slot, isolate()->factory()->home_object_symbol()); } @@ -1141,7 +1146,7 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, Register temp = ebx; for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { - if (s->num_heap_slots() > 0) { + if (s->NeedsContext()) { if (s->calls_sloppy_eval()) { // Check that extension is "the hole". __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), @@ -1189,20 +1194,6 @@ void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy, } } - -void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, - TypeofMode typeof_mode) { -#ifdef DEBUG - Variable* var = proxy->var(); - DCHECK(var->IsUnallocatedOrGlobalSlot() || - (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); -#endif - __ mov(LoadGlobalDescriptor::SlotRegister(), - Immediate(SmiFromSlot(proxy->VariableFeedbackSlot()))); - CallLoadGlobalIC(typeof_mode); -} - - void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, TypeofMode typeof_mode) { SetExpressionPosition(proxy); @@ -1212,7 +1203,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, // Three cases: global variables, lookup variables, and all other types of // variables. switch (var->location()) { - case VariableLocation::GLOBAL: case VariableLocation::UNALLOCATED: { Comment cmnt(masm_, "[ Global variable"); EmitGlobalVariableLoad(proxy, typeof_mode); @@ -1339,10 +1329,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { if (property->emit_store()) { VisitForAccumulatorValue(value); DCHECK(StoreDescriptor::ValueRegister().is(eax)); - __ mov(StoreDescriptor::NameRegister(), Immediate(key->value())); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); - EmitLoadStoreICSlot(property->GetSlot(0)); - CallStoreIC(); + CallStoreIC(property->GetSlot(0), key->value()); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); if (NeedsHomeObject(value)) { EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); @@ -1506,6 +1494,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ mov(ecx, Immediate(constant_elements)); FastCloneShallowArrayStub stub(isolate(), allocation_site_mode); __ CallStub(&stub); + RestoreContext(); } PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER); @@ -1515,8 +1504,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { // Emit code to evaluate all the non-constant subexpressions and to store // them into the newly cloned array. - int array_index = 0; - for (; array_index < length; array_index++) { + for (int array_index = 0; array_index < length; array_index++) { Expression* subexpr = subexprs->at(array_index); DCHECK(!subexpr->IsSpread()); @@ -1533,31 +1521,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { __ mov(StoreDescriptor::NameRegister(), Immediate(Smi::FromInt(array_index))); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); - EmitLoadStoreICSlot(expr->LiteralFeedbackSlot()); - Handle<Code> ic = - CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); - CallIC(ic); - PrepareForBailoutForId(expr->GetIdForElement(array_index), - BailoutState::NO_REGISTERS); - } - - // In case the array literal contains spread expressions it has two parts. The - // first part is the "static" array which has a literal index is handled - // above. The second part is the part after the first spread expression - // (inclusive) and these elements gets appended to the array. Note that the - // number elements an iterable produces is unknown ahead of time. - if (array_index < length && result_saved) { - PopOperand(eax); - result_saved = false; - } - for (; array_index < length; array_index++) { - Expression* subexpr = subexprs->at(array_index); - - PushOperand(eax); - DCHECK(!subexpr->IsSpread()); - VisitForStackValue(subexpr); - CallRuntimeWithOperands(Runtime::kAppendElement); - + CallKeyedStoreIC(expr->LiteralFeedbackSlot()); PrepareForBailoutForId(expr->GetIdForElement(array_index), BailoutState::NO_REGISTERS); } @@ -1902,7 +1866,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { for (int i = 0; i < lit->properties()->length(); i++) { - ObjectLiteral::Property* property = lit->properties()->at(i); + ClassLiteral::Property* property = lit->properties()->at(i); Expression* value = property->value(); if (property->is_static()) { @@ -1927,25 +1891,25 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { } switch (property->kind()) { - case ObjectLiteral::Property::CONSTANT: - case ObjectLiteral::Property::MATERIALIZED_LITERAL: - case ObjectLiteral::Property::PROTOTYPE: - UNREACHABLE(); - case ObjectLiteral::Property::COMPUTED: + case ClassLiteral::Property::METHOD: PushOperand(Smi::FromInt(DONT_ENUM)); PushOperand(Smi::FromInt(property->NeedsSetFunctionName())); CallRuntimeWithOperands(Runtime::kDefineDataPropertyInLiteral); break; - case ObjectLiteral::Property::GETTER: + case ClassLiteral::Property::GETTER: PushOperand(Smi::FromInt(DONT_ENUM)); CallRuntimeWithOperands(Runtime::kDefineGetterPropertyUnchecked); break; - case ObjectLiteral::Property::SETTER: + case ClassLiteral::Property::SETTER: PushOperand(Smi::FromInt(DONT_ENUM)); CallRuntimeWithOperands(Runtime::kDefineSetterPropertyUnchecked); break; + + case ClassLiteral::Property::FIELD: + UNREACHABLE(); + break; } } } @@ -1980,10 +1944,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, VisitForAccumulatorValue(prop->obj()); __ Move(StoreDescriptor::ReceiverRegister(), eax); PopOperand(StoreDescriptor::ValueRegister()); // Restore value. - __ mov(StoreDescriptor::NameRegister(), - prop->key()->AsLiteral()->value()); - EmitLoadStoreICSlot(slot); - CallStoreIC(); + CallStoreIC(slot, prop->key()->AsLiteral()->value()); break; } case NAMED_SUPER_PROPERTY: { @@ -2030,10 +1991,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, __ Move(StoreDescriptor::NameRegister(), eax); PopOperand(StoreDescriptor::ReceiverRegister()); // Receiver. PopOperand(StoreDescriptor::ValueRegister()); // Restore value. - EmitLoadStoreICSlot(slot); - Handle<Code> ic = - CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); - CallIC(ic); + CallKeyedStoreIC(slot); break; } } @@ -2056,13 +2014,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, FeedbackVectorSlot slot) { if (var->IsUnallocated()) { // Global var, const, or let. - __ mov(StoreDescriptor::NameRegister(), var->name()); __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); __ mov(StoreDescriptor::ReceiverRegister(), ContextOperand(StoreDescriptor::ReceiverRegister(), Context::EXTENSION_INDEX)); - EmitLoadStoreICSlot(slot); - CallStoreIC(); + CallStoreIC(slot, var->name()); } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { DCHECK(!var->IsLookupSlot()); @@ -2078,10 +2034,10 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ CallRuntime(Runtime::kThrowReferenceError); __ bind(&assign); } - if (var->mode() == CONST) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } else { + if (var->mode() != CONST) { EmitStoreToStackLocalOrContextSlot(var, location); + } else if (var->throw_on_const_assignment(language_mode())) { + __ CallRuntime(Runtime::kThrowConstAssignError); } } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { // Initializing assignment to const {this} needs a write barrier. @@ -2096,7 +2052,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, __ bind(&uninitialized_this); EmitStoreToStackLocalOrContextSlot(var, location); - } else if (!var->is_const_mode() || op == Token::INIT) { + } else { + DCHECK(var->mode() != CONST || op == Token::INIT); if (var->IsLookupSlot()) { // Assignment to var. __ Push(Immediate(var->name())); @@ -2117,13 +2074,6 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, } EmitStoreToStackLocalOrContextSlot(var, location); } - - } else { - DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); - if (is_strict(language_mode())) { - __ CallRuntime(Runtime::kThrowConstAssignError); - } - // Silently ignore store in sloppy mode. } } @@ -2136,10 +2086,8 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { DCHECK(prop != NULL); DCHECK(prop->key()->IsLiteral()); - __ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value()); PopOperand(StoreDescriptor::ReceiverRegister()); - EmitLoadStoreICSlot(expr->AssignmentSlot()); - CallStoreIC(); + CallStoreIC(expr->AssignmentSlot(), prop->key()->AsLiteral()->value()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(eax); } @@ -2182,10 +2130,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { PopOperand(StoreDescriptor::NameRegister()); // Key. PopOperand(StoreDescriptor::ReceiverRegister()); DCHECK(StoreDescriptor::ValueRegister().is(eax)); - Handle<Code> ic = - CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); - EmitLoadStoreICSlot(expr->AssignmentSlot()); - CallIC(ic); + CallKeyedStoreIC(expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(eax); } @@ -2723,25 +2668,6 @@ void FullCodeGenerator::EmitClassOf(CallRuntime* expr) { } -void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) { - ZoneList<Expression*>* args = expr->arguments(); - DCHECK(args->length() == 1); - - VisitForAccumulatorValue(args->at(0)); - - Label done; - StringCharFromCodeGenerator generator(eax, ebx); - generator.GenerateFast(masm_); - __ jmp(&done); - - NopRuntimeCallHelper call_helper; - generator.GenerateSlow(masm_, call_helper); - - __ bind(&done); - context()->Plug(ebx); -} - - void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) { ZoneList<Expression*>* args = expr->arguments(); DCHECK(args->length() == 2); @@ -2936,7 +2862,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { // "delete this" is allowed. bool is_this = var->is_this(); DCHECK(is_sloppy(language_mode()) || is_this); - if (var->IsUnallocatedOrGlobalSlot()) { + if (var->IsUnallocated()) { __ mov(eax, NativeContextOperand()); __ push(ContextOperand(eax, Context::EXTENSION_INDEX)); __ push(Immediate(var->name())); @@ -3230,11 +3156,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } break; case NAMED_PROPERTY: { - __ mov(StoreDescriptor::NameRegister(), - prop->key()->AsLiteral()->value()); PopOperand(StoreDescriptor::ReceiverRegister()); - EmitLoadStoreICSlot(expr->CountSlot()); - CallStoreIC(); + CallStoreIC(expr->CountSlot(), prop->key()->AsLiteral()->value()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); if (expr->is_postfix()) { if (!context()->IsEffect()) { @@ -3272,10 +3195,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { case KEYED_PROPERTY: { PopOperand(StoreDescriptor::NameRegister()); PopOperand(StoreDescriptor::ReceiverRegister()); - Handle<Code> ic = - CodeFactory::KeyedStoreIC(isolate(), language_mode()).code(); - EmitLoadStoreICSlot(expr->CountSlot()); - CallIC(ic); + CallKeyedStoreIC(expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); if (expr->is_postfix()) { // Result is on the stack |