summaryrefslogtreecommitdiff
path: root/deps/v8/src/x64/full-codegen-x64.cc
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2014-03-18 00:33:01 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2014-03-18 00:33:01 +0400
commit4d140746f0978da2a6493b92d3b6de4b18f3394d (patch)
tree69d76bb397ca1dde203a5d7535ecc33c58c85f25 /deps/v8/src/x64/full-codegen-x64.cc
parentee4b9b552dee37ed5844da6c261e4d28a33d3c13 (diff)
downloadnode-new-4d140746f0978da2a6493b92d3b6de4b18f3394d.tar.gz
deps: update v8 to 3.24.35.17
Diffstat (limited to 'deps/v8/src/x64/full-codegen-x64.cc')
-rw-r--r--deps/v8/src/x64/full-codegen-x64.cc164
1 files changed, 82 insertions, 82 deletions
diff --git a/deps/v8/src/x64/full-codegen-x64.cc b/deps/v8/src/x64/full-codegen-x64.cc
index badf18ed67..621eacc708 100644
--- a/deps/v8/src/x64/full-codegen-x64.cc
+++ b/deps/v8/src/x64/full-codegen-x64.cc
@@ -118,9 +118,6 @@ void FullCodeGenerator::Generate() {
CompilationInfo* info = info_;
handler_table_ =
isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
-
- InitializeFeedbackVector();
-
profiling_counter_ = isolate()->factory()->NewCell(
Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
SetFunctionPosition(function());
@@ -641,7 +638,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_false,
Label* fall_through) {
Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
- CallIC(ic, condition->test_id());
+ CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
__ testq(result_register(), result_register());
// The stub returns nonzero for true.
Split(not_zero, if_true, if_false, fall_through);
@@ -994,7 +991,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Record position before stub call for type feedback.
SetSourcePosition(clause->position());
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
- CallIC(ic, clause->CompareId());
+ CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
patch_site.EmitPatchInfo();
Label skip;
@@ -1038,7 +1035,6 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Comment cmnt(masm_, "[ ForInStatement");
- int slot = stmt->ForInFeedbackSlot();
SetStatementPosition(stmt);
Label loop, exit;
@@ -1127,15 +1123,14 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
Label non_proxy;
__ bind(&fixed_array);
- Handle<Object> feedback = Handle<Object>(
- Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
- isolate());
- StoreFeedbackVectorSlot(slot, feedback);
+ Handle<Cell> cell = isolate()->factory()->NewCell(
+ Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
+ isolate()));
+ RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
+ __ Move(rbx, cell);
+ __ Move(FieldOperand(rbx, Cell::kValueOffset),
+ Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
- // No need for a write barrier, we are storing a Smi in the feedback vector.
- __ Move(rbx, FeedbackVector());
- __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
- Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker));
__ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
__ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
@@ -1444,7 +1439,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
// variables.
switch (var->location()) {
case Variable::UNALLOCATED: {
- Comment cmnt(masm_, "[ Global variable");
+ Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in rcx and the global
// object on the stack.
__ Move(rcx, var->name());
@@ -1457,8 +1452,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
case Variable::PARAMETER:
case Variable::LOCAL:
case Variable::CONTEXT: {
- Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
- : "[ Stack slot");
+ Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
if (var->binding_needs_init()) {
// var->scope() may be NULL when the proxy is located in eval code and
// refers to a potential outside binding. Currently those bindings are
@@ -1520,12 +1514,12 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
}
case Variable::LOOKUP: {
- Comment cmnt(masm_, "[ Lookup slot");
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
+ Comment cmnt(masm_, "Lookup slot");
__ push(rsi); // Context.
__ Push(var->name());
__ CallRuntime(Runtime::kLoadContextSlot, 2);
@@ -1664,7 +1658,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value);
__ Move(rcx, key->value());
__ movp(rdx, Operand(rsp, 0));
- CallStoreIC(key->LiteralFeedbackId());
+ CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
} else {
VisitForEffect(value);
@@ -2079,7 +2073,7 @@ void FullCodeGenerator::VisitYield(Yield* expr) {
__ movp(rdx, Operand(rsp, kPointerSize));
__ movp(rax, Operand(rsp, 2 * kPointerSize));
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
- CallIC(ic, TypeFeedbackId::None());
+ CallIC(ic, NOT_CONTEXTUAL, TypeFeedbackId::None());
__ movp(rdi, rax);
__ movp(Operand(rsp, 2 * kPointerSize), rdi);
CallFunctionStub stub(1, CALL_AS_METHOD);
@@ -2270,7 +2264,7 @@ void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
- CallIC(ic, prop->PropertyFeedbackId());
+ CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
}
@@ -2292,7 +2286,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
__ movp(rax, rcx);
BinaryOpICStub stub(op, mode);
- CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
+ CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
+ expr->BinaryOperationFeedbackId());
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
@@ -2341,7 +2336,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
__ pop(rdx);
BinaryOpICStub stub(op, mode);
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
- CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
+ CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
+ expr->BinaryOperationFeedbackId());
patch_site.EmitPatchInfo();
context()->Plug(rax);
}
@@ -2379,7 +2375,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
__ movp(rdx, rax);
__ pop(rax); // Restore value.
__ Move(rcx, prop->key()->AsLiteral()->value());
- CallStoreIC();
+ CallStoreIC(NOT_CONTEXTUAL);
break;
}
case KEYED_PROPERTY: {
@@ -2400,58 +2396,44 @@ void FullCodeGenerator::EmitAssignment(Expression* expr) {
}
-void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
- Variable* var, MemOperand location) {
- __ movp(location, rax);
- if (var->IsContextSlot()) {
- __ movp(rdx, rax);
- __ RecordWriteContextSlot(
- rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
- }
-}
-
-
-void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, LanguageMode mode) {
- __ push(rax); // Value.
- __ push(rsi); // Context.
- __ Push(name);
- __ Push(Smi::FromInt(mode));
- __ CallRuntime(Runtime::kStoreContextSlot, 4);
-}
-
-
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
if (var->IsUnallocated()) {
// Global var, const, or let.
__ Move(rcx, var->name());
__ movp(rdx, GlobalObjectOperand());
- CallStoreIC();
-
+ CallStoreIC(CONTEXTUAL);
} else if (op == Token::INIT_CONST) {
// Const initializers need a write barrier.
ASSERT(!var->IsParameter()); // No const parameters.
- if (var->IsLookupSlot()) {
- __ push(rax);
- __ push(rsi);
- __ Push(var->name());
- __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
- } else {
- ASSERT(var->IsStackLocal() || var->IsContextSlot());
+ if (var->IsStackLocal()) {
Label skip;
- MemOperand location = VarOperand(var, rcx);
- __ movp(rdx, location);
+ __ movp(rdx, StackOperand(var));
__ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
__ j(not_equal, &skip);
- EmitStoreToStackLocalOrContextSlot(var, location);
+ __ movp(StackOperand(var), rax);
__ bind(&skip);
+ } else {
+ ASSERT(var->IsContextSlot() || var->IsLookupSlot());
+ // Like var declarations, const declarations are hoisted to function
+ // scope. However, unlike var initializers, const initializers are
+ // able to drill a hole to that function context, even from inside a
+ // 'with' context. We thus bypass the normal static scope lookup for
+ // var->IsContextSlot().
+ __ push(rax);
+ __ push(rsi);
+ __ Push(var->name());
+ __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
}
} else if (var->mode() == LET && op != Token::INIT_LET) {
// Non-initializing assignment to let variable needs a write barrier.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
+ __ push(rax); // Value.
+ __ push(rsi); // Context.
+ __ Push(var->name());
+ __ Push(Smi::FromInt(language_mode()));
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
} else {
ASSERT(var->IsStackAllocated() || var->IsContextSlot());
Label assign;
@@ -2462,16 +2444,18 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ Push(var->name());
__ CallRuntime(Runtime::kThrowReferenceError, 1);
__ bind(&assign);
- EmitStoreToStackLocalOrContextSlot(var, location);
+ __ movp(location, rax);
+ if (var->IsContextSlot()) {
+ __ movp(rdx, rax);
+ __ RecordWriteContextSlot(
+ rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
+ }
}
} else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
// Assignment to var or initializing assignment to let/const
// in harmony mode.
- if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), language_mode());
- } else {
- ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ if (var->IsStackAllocated() || var->IsContextSlot()) {
MemOperand location = VarOperand(var, rcx);
if (generate_debug_code_ && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
@@ -2479,7 +2463,20 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
__ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
__ Check(equal, kLetBindingReInitialization);
}
- EmitStoreToStackLocalOrContextSlot(var, location);
+ // Perform the assignment.
+ __ movp(location, rax);
+ if (var->IsContextSlot()) {
+ __ movp(rdx, rax);
+ __ RecordWriteContextSlot(
+ rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
+ }
+ } else {
+ ASSERT(var->IsLookupSlot());
+ __ push(rax); // Value.
+ __ push(rsi); // Context.
+ __ Push(var->name());
+ __ Push(Smi::FromInt(language_mode()));
+ __ CallRuntime(Runtime::kStoreContextSlot, 4);
}
}
// Non-initializing assignments to consts are ignored.
@@ -2496,7 +2493,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
SetSourcePosition(expr->position());
__ Move(rcx, prop->key()->AsLiteral()->value());
__ pop(rdx);
- CallStoreIC(expr->AssignmentFeedbackId());
+ CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
@@ -2513,7 +2510,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
- CallIC(ic, expr->AssignmentFeedbackId());
+ CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
@@ -2540,8 +2537,10 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
void FullCodeGenerator::CallIC(Handle<Code> code,
+ ContextualMode mode,
TypeFeedbackId ast_id) {
ic_total_count_++;
+ ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
__ call(code, RelocInfo::CODE_TARGET, ast_id);
}
@@ -2651,15 +2650,15 @@ void FullCodeGenerator::EmitCallWithStub(Call* expr) {
SetSourcePosition(expr->position());
Handle<Object> uninitialized =
- TypeFeedbackInfo::UninitializedSentinel(isolate());
- StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
- __ Move(rbx, FeedbackVector());
- __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
+ TypeFeedbackCells::UninitializedSentinel(isolate());
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
+ RecordTypeFeedbackCell(expr->CallFeedbackId(), cell);
+ __ Move(rbx, cell);
// Record call targets in unoptimized code.
CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
- __ CallStub(&stub);
+ __ CallStub(&stub, expr->CallFeedbackId());
RecordJSReturnSite(expr);
// Restore context register.
__ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
@@ -2831,10 +2830,10 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
// Record call targets in unoptimized code, but not in the snapshot.
Handle<Object> uninitialized =
- TypeFeedbackInfo::UninitializedSentinel(isolate());
- StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
- __ Move(rbx, FeedbackVector());
- __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
+ TypeFeedbackCells::UninitializedSentinel(isolate());
+ Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized);
+ RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell);
+ __ Move(rbx, cell);
CallConstructStub stub(RECORD_CALL_TARGET);
__ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
@@ -4410,7 +4409,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ movp(rdx, rax);
__ Move(rax, Smi::FromInt(1));
BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
- CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId());
+ CallIC(stub.GetCode(isolate()),
+ NOT_CONTEXTUAL,
+ expr->CountBinOpFeedbackId());
patch_site.EmitPatchInfo();
__ bind(&done);
@@ -4441,7 +4442,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
case NAMED_PROPERTY: {
__ Move(rcx, prop->key()->AsLiteral()->value());
__ pop(rdx);
- CallStoreIC(expr->CountStoreFeedbackId());
+ CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@@ -4458,7 +4459,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
Handle<Code> ic = is_classic_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize()
: isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
- CallIC(ic, expr->CountStoreFeedbackId());
+ CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
@@ -4479,7 +4480,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
ASSERT(!context()->IsTest());
if (proxy != NULL && proxy->var()->IsUnallocated()) {
- Comment cmnt(masm_, "[ Global variable");
+ Comment cmnt(masm_, "Global variable");
__ Move(rcx, proxy->name());
__ movp(rax, GlobalObjectOperand());
// Use a regular load, not a contextual load, to avoid a reference
@@ -4488,7 +4489,6 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
PrepareForBailout(expr, TOS_REG);
context()->Plug(rax);
} else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
- Comment cmnt(masm_, "[ Lookup slot");
Label done, slow;
// Generate code for loading from variables potentially shadowed
@@ -4647,7 +4647,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
// Record position and call the compare IC.
SetSourcePosition(expr->position());
Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
- CallIC(ic, expr->CompareOperationFeedbackId());
+ CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
patch_site.EmitPatchInfo();
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
@@ -4682,7 +4682,7 @@ void FullCodeGenerator::EmitLiteralCompareNil(CompareOperation* expr,
Split(equal, if_true, if_false, fall_through);
} else {
Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
- CallIC(ic, expr->CompareOperationFeedbackId());
+ CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
__ testq(rax, rax);
Split(not_zero, if_true, if_false, fall_through);
}