summaryrefslogtreecommitdiff
path: root/deps/v8/src/full-codegen/ia32/full-codegen-ia32.cc
diff options
context:
space:
mode:
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.cc176
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