aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc')
-rw-r--r--deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc180
1 files changed, 48 insertions, 132 deletions
diff --git a/deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc b/deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc
index a4f32da2ef..1854f102be 100644
--- a/deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc
+++ b/deps/v8/src/full-codegen/arm64/full-codegen-arm64.cc
@@ -4,14 +4,16 @@
#if V8_TARGET_ARCH_ARM64
+#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/ic/ic.h"
-#include "src/parsing/parser.h"
#include "src/arm64/code-stubs-arm64.h"
#include "src/arm64/frames-arm64.h"
@@ -130,6 +132,20 @@ 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");
+ __ Ldr(x11, FieldMemOperand(x1, JSFunction::kLiteralsOffset));
+ __ Ldr(x11, FieldMemOperand(x11, LiteralsArray::kFeedbackVectorOffset));
+ __ Ldr(x10, FieldMemOperand(x11, TypeFeedbackVector::kInvocationCountIndex *
+ kPointerSize +
+ TypeFeedbackVector::kHeaderSize));
+ __ Add(x10, x10, Operand(Smi::FromInt(1)));
+ __ Str(x10, FieldMemOperand(x11, TypeFeedbackVector::kInvocationCountIndex *
+ kPointerSize +
+ TypeFeedbackVector::kHeaderSize));
+ }
+
// Reserve space on the stack for locals.
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
@@ -170,13 +186,13 @@ void FullCodeGenerator::Generate() {
bool function_in_register_x1 = true;
- if (info->scope()->num_heap_slots() > 0) {
+ if (info->scope()->NeedsContext()) {
// Argument to NewContext is the function, which is still in x1.
Comment cmnt(masm_, "[ Allocate context");
bool need_write_barrier = true;
int slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
if (info->scope()->is_script_scope()) {
- __ Mov(x10, Operand(info->scope()->GetScopeInfo(info->isolate())));
+ __ Mov(x10, Operand(info->scope()->scope_info()));
__ Push(x1, x10);
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
@@ -261,9 +277,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_x1) {
__ Ldr(x1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
@@ -765,7 +780,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();
@@ -816,7 +830,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());
@@ -1126,6 +1139,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);
// TODO(all): We could use a callee saved register to avoid popping.
__ Pop(x0);
__ Add(x0, x0, Smi::FromInt(1));
@@ -1149,11 +1163,8 @@ void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
FeedbackVectorSlot slot) {
DCHECK(NeedsHomeObject(initializer));
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
- __ Mov(StoreDescriptor::NameRegister(),
- Operand(isolate()->factory()->home_object_symbol()));
__ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
- EmitLoadStoreICSlot(slot);
- CallStoreIC();
+ CallStoreIC(slot, isolate()->factory()->home_object_symbol());
}
@@ -1162,11 +1173,8 @@ void FullCodeGenerator::EmitSetHomeObjectAccumulator(Expression* initializer,
FeedbackVectorSlot slot) {
DCHECK(NeedsHomeObject(initializer));
__ Move(StoreDescriptor::ReceiverRegister(), x0);
- __ Mov(StoreDescriptor::NameRegister(),
- Operand(isolate()->factory()->home_object_symbol()));
__ Peek(StoreDescriptor::ValueRegister(), offset * kPointerSize);
- EmitLoadStoreICSlot(slot);
- CallStoreIC();
+ CallStoreIC(slot, isolate()->factory()->home_object_symbol());
}
@@ -1206,7 +1214,7 @@ MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
Register temp = x11;
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".
__ Ldr(temp, ContextMemOperand(context, Context::EXTENSION_INDEX));
@@ -1254,20 +1262,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(),
- SmiFromSlot(proxy->VariableFeedbackSlot()));
- CallLoadGlobalIC(typeof_mode);
-}
-
-
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
// Record position before possible IC call.
@@ -1278,7 +1272,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);
@@ -1401,10 +1394,8 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
if (property->emit_store()) {
VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(x0));
- __ Mov(StoreDescriptor::NameRegister(), Operand(key->value()));
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
- EmitLoadStoreICSlot(property->GetSlot(0));
- CallStoreIC();
+ CallStoreIC(property->GetSlot(0), key->value());
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) {
@@ -1572,6 +1563,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
} else {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
+ RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
@@ -1581,8 +1573,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());
@@ -1598,31 +1589,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ Mov(StoreDescriptor::NameRegister(), Smi::FromInt(array_index));
__ Peek(StoreDescriptor::ReceiverRegister(), 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(x0);
- result_saved = false;
- }
- for (; array_index < length; array_index++) {
- Expression* subexpr = subexprs->at(array_index);
-
- PushOperand(x0);
- DCHECK(!subexpr->IsSpread());
- VisitForStackValue(subexpr);
- CallRuntimeWithOperands(Runtime::kAppendElement);
+ CallKeyedStoreIC(expr->LiteralFeedbackSlot());
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
@@ -1892,7 +1859,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
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();
Register scratch = x1;
@@ -1919,26 +1886,23 @@ 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:
default:
UNREACHABLE();
}
@@ -1967,10 +1931,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
// this copy.
__ Mov(StoreDescriptor::ReceiverRegister(), x0);
PopOperand(StoreDescriptor::ValueRegister()); // Restore value.
- __ Mov(StoreDescriptor::NameRegister(),
- Operand(prop->key()->AsLiteral()->value()));
- EmitLoadStoreICSlot(slot);
- CallStoreIC();
+ CallStoreIC(slot, prop->key()->AsLiteral()->value());
break;
}
case NAMED_SUPER_PROPERTY: {
@@ -2017,10 +1978,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr,
__ Mov(StoreDescriptor::NameRegister(), x0);
PopOperands(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::ValueRegister());
- EmitLoadStoreICSlot(slot);
- Handle<Code> ic =
- CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
- CallIC(ic);
+ CallKeyedStoreIC(slot);
break;
}
}
@@ -2046,10 +2004,8 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment");
if (var->IsUnallocated()) {
// Global var, const, or let.
- __ Mov(StoreDescriptor::NameRegister(), Operand(var->name()));
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
- EmitLoadStoreICSlot(slot);
- CallStoreIC();
+ CallStoreIC(slot, var->name());
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot());
@@ -2065,10 +2021,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.
@@ -2083,7 +2039,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(var->name());
@@ -2103,13 +2060,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.
}
}
@@ -2121,11 +2071,8 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
DCHECK(prop != NULL);
DCHECK(prop->key()->IsLiteral());
- __ Mov(StoreDescriptor::NameRegister(),
- Operand(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(x0);
@@ -2170,10 +2117,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
StoreDescriptor::ReceiverRegister());
DCHECK(StoreDescriptor::ValueRegister().is(x0));
- 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(x0);
@@ -2746,28 +2690,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;
- Register code = x0;
- Register result = x1;
-
- StringCharFromCodeGenerator generator(code, result);
- generator.GenerateFast(masm_);
- __ B(&done);
-
- NopRuntimeCallHelper call_helper;
- generator.GenerateSlow(masm_, call_helper);
-
- __ Bind(&done);
- context()->Plug(result);
-}
-
-
void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
DCHECK(args->length() == 2);
@@ -2971,7 +2893,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()) {
__ LoadGlobalObject(x12);
__ Mov(x11, Operand(var->name()));
__ Push(x12, x11);
@@ -3254,11 +3176,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
}
break;
case NAMED_PROPERTY: {
- __ Mov(StoreDescriptor::NameRegister(),
- Operand(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()) {
@@ -3296,10 +3215,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()) {
if (!context()->IsEffect()) {