#if V8_TARGET_ARCH_X87
+#include "src/code-factory.h"
#include "src/code-stubs.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/debug.h"
#include "src/full-codegen.h"
+#include "src/ic/ic.h"
#include "src/isolate-inl.h"
#include "src/parser.h"
#include "src/scopes.h"
-#include "src/stub-cache.h"
namespace v8 {
namespace internal {
}
~JumpPatchSite() {
- ASSERT(patch_site_.is_bound() == info_emitted_);
+ DCHECK(patch_site_.is_bound() == info_emitted_);
}
void EmitJumpIfNotSmi(Register reg,
void EmitPatchInfo() {
if (patch_site_.is_bound()) {
int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
- ASSERT(is_uint8(delta_to_patch_site));
+ DCHECK(is_uint8(delta_to_patch_site));
__ test(eax, Immediate(delta_to_patch_site));
#ifdef DEBUG
info_emitted_ = true;
private:
// jc will be patched with jz, jnc will become jnz.
void EmitJump(Condition cc, Label* target, Label::Distance distance) {
- ASSERT(!patch_site_.is_bound() && !info_emitted_);
- ASSERT(cc == carry || cc == not_carry);
+ DCHECK(!patch_site_.is_bound() && !info_emitted_);
+ DCHECK(cc == carry || cc == not_carry);
__ bind(&patch_site_);
__ j(cc, target, distance);
}
__ j(not_equal, &ok, Label::kNear);
__ mov(ecx, GlobalObjectOperand());
- __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
+ __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalProxyOffset));
__ mov(Operand(esp, receiver_offset), ecx);
{ Comment cmnt(masm_, "[ Allocate locals");
int locals_count = info->scope()->num_stack_slots();
// Generators allocate locals, if any, in context slots.
- ASSERT(!info->function()->is_generator() || locals_count == 0);
+ DCHECK(!info->function()->is_generator() || locals_count == 0);
if (locals_count == 1) {
__ push(Immediate(isolate()->factory()->undefined_value()));
} else if (locals_count > 1) {
if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
__ push(edi);
__ Push(info->scope()->GetScopeInfo());
- __ CallRuntime(Runtime::kHiddenNewGlobalContext, 2);
+ __ CallRuntime(Runtime::kNewGlobalContext, 2);
} else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
FastNewContextStub stub(isolate(), heap_slots);
__ CallStub(&stub);
need_write_barrier = false;
} else {
__ push(edi);
- __ CallRuntime(Runtime::kHiddenNewFunctionContext, 1);
+ __ CallRuntime(Runtime::kNewFunctionContext, 1);
}
function_in_register = false;
// Context is returned in eax. It replaces the context passed to us.
__ mov(Operand(esi, context_offset), eax);
// Update the write barrier. This clobbers eax and ebx.
if (need_write_barrier) {
- __ RecordWriteContextSlot(esi,
- context_offset,
- eax,
- ebx);
+ __ RecordWriteContextSlot(esi, context_offset, eax, ebx,
+ kDontSaveFPRegs);
} else if (FLAG_debug_code) {
Label done;
__ JumpIfInNewSpace(esi, eax, &done, Label::kNear);
// constant.
if (scope()->is_function_scope() && scope()->function() != NULL) {
VariableDeclaration* function = scope()->function();
- ASSERT(function->proxy()->var()->mode() == CONST ||
+ DCHECK(function->proxy()->var()->mode() == CONST ||
function->proxy()->var()->mode() == CONST_LEGACY);
- ASSERT(function->proxy()->var()->location() != Variable::UNALLOCATED);
+ DCHECK(function->proxy()->var()->location() != Variable::UNALLOCATED);
VisitVariableDeclaration(function);
}
VisitDeclarations(scope()->declarations());
}
{ Comment cmnt(masm_, "[ Body");
- ASSERT(loop_depth() == 0);
+ DCHECK(loop_depth() == 0);
VisitStatements(function()->body());
- ASSERT(loop_depth() == 0);
+ DCHECK(loop_depth() == 0);
}
}
Comment cmnt(masm_, "[ Back edge bookkeeping");
Label ok;
- ASSERT(back_edge_target->is_bound());
+ DCHECK(back_edge_target->is_bound());
int distance = masm_->SizeOfCodeGeneratedSince(back_edge_target);
int weight = Min(kMaxBackEdgeWeight,
Max(1, distance / kCodeSizeMultiplier));
__ Ret(arguments_bytes, ecx);
// Check that the size of the code used for returning is large enough
// for the debugger's requirements.
- ASSERT(Assembler::kJSReturnSequenceLength <=
+ DCHECK(Assembler::kJSReturnSequenceLength <=
masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
}
void FullCodeGenerator::EffectContext::Plug(Variable* var) const {
- ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ DCHECK(var->IsStackAllocated() || var->IsContextSlot());
}
void FullCodeGenerator::AccumulatorValueContext::Plug(Variable* var) const {
- ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ DCHECK(var->IsStackAllocated() || var->IsContextSlot());
codegen()->GetVar(result_register(), var);
}
void FullCodeGenerator::StackValueContext::Plug(Variable* var) const {
- ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ DCHECK(var->IsStackAllocated() || var->IsContextSlot());
MemOperand operand = codegen()->VarOperand(var, result_register());
// Memory operands can be pushed directly.
__ push(operand);
true,
true_label_,
false_label_);
- ASSERT(!lit->IsUndetectableObject()); // There are no undetectable literals.
+ DCHECK(!lit->IsUndetectableObject()); // There are no undetectable literals.
if (lit->IsUndefined() || lit->IsNull() || lit->IsFalse()) {
if (false_label_ != fall_through_) __ jmp(false_label_);
} else if (lit->IsTrue() || lit->IsJSObject()) {
void FullCodeGenerator::EffectContext::DropAndPlug(int count,
Register reg) const {
- ASSERT(count > 0);
+ DCHECK(count > 0);
__ Drop(count);
}
void FullCodeGenerator::AccumulatorValueContext::DropAndPlug(
int count,
Register reg) const {
- ASSERT(count > 0);
+ DCHECK(count > 0);
__ Drop(count);
__ Move(result_register(), reg);
}
void FullCodeGenerator::StackValueContext::DropAndPlug(int count,
Register reg) const {
- ASSERT(count > 0);
+ DCHECK(count > 0);
if (count > 1) __ Drop(count - 1);
__ mov(Operand(esp, 0), reg);
}
void FullCodeGenerator::TestContext::DropAndPlug(int count,
Register reg) const {
- ASSERT(count > 0);
+ DCHECK(count > 0);
// For simplicity we always test the accumulator register.
__ Drop(count);
__ Move(result_register(), reg);
void FullCodeGenerator::EffectContext::Plug(Label* materialize_true,
Label* materialize_false) const {
- ASSERT(materialize_true == materialize_false);
+ DCHECK(materialize_true == materialize_false);
__ bind(materialize_true);
}
void FullCodeGenerator::TestContext::Plug(Label* materialize_true,
Label* materialize_false) const {
- ASSERT(materialize_true == true_label_);
- ASSERT(materialize_false == false_label_);
+ DCHECK(materialize_true == true_label_);
+ DCHECK(materialize_false == false_label_);
}
MemOperand FullCodeGenerator::StackOperand(Variable* var) {
- ASSERT(var->IsStackAllocated());
+ DCHECK(var->IsStackAllocated());
// Offset is negative because higher indexes are at lower addresses.
int offset = -var->index() * kPointerSize;
// Adjust by a (parameter or local) base offset.
MemOperand FullCodeGenerator::VarOperand(Variable* var, Register scratch) {
- ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ DCHECK(var->IsContextSlot() || var->IsStackAllocated());
if (var->IsContextSlot()) {
int context_chain_length = scope()->ContextChainLength(var->scope());
__ LoadContext(scratch, context_chain_length);
void FullCodeGenerator::GetVar(Register dest, Variable* var) {
- ASSERT(var->IsContextSlot() || var->IsStackAllocated());
+ DCHECK(var->IsContextSlot() || var->IsStackAllocated());
MemOperand location = VarOperand(var, dest);
__ mov(dest, location);
}
Register src,
Register scratch0,
Register scratch1) {
- ASSERT(var->IsContextSlot() || var->IsStackAllocated());
- ASSERT(!scratch0.is(src));
- ASSERT(!scratch0.is(scratch1));
- ASSERT(!scratch1.is(src));
+ DCHECK(var->IsContextSlot() || var->IsStackAllocated());
+ DCHECK(!scratch0.is(src));
+ DCHECK(!scratch0.is(scratch1));
+ DCHECK(!scratch1.is(src));
MemOperand location = VarOperand(var, scratch0);
__ mov(location, src);
// Emit the write barrier code if the location is in the heap.
if (var->IsContextSlot()) {
int offset = Context::SlotOffset(var->index());
- ASSERT(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
- __ RecordWriteContextSlot(scratch0, offset, src, scratch1);
+ DCHECK(!scratch0.is(esi) && !src.is(esi) && !scratch1.is(esi));
+ __ RecordWriteContextSlot(scratch0, offset, src, scratch1, kDontSaveFPRegs);
}
}
void FullCodeGenerator::EmitDebugCheckDeclarationContext(Variable* variable) {
// The variable in the declaration always resides in the current context.
- ASSERT_EQ(0, scope()->ContextChainLength(variable->scope()));
+ DCHECK_EQ(0, scope()->ContextChainLength(variable->scope()));
if (generate_debug_code_) {
// Check that we're not inside a with or catch context.
__ mov(ebx, FieldOperand(esi, HeapObject::kMapOffset));
__ push(esi);
__ push(Immediate(variable->name()));
// VariableDeclaration nodes are always introduced in one of four modes.
- ASSERT(IsDeclaredVariableMode(mode));
+ DCHECK(IsDeclaredVariableMode(mode));
PropertyAttributes attr =
IsImmutableVariableMode(mode) ? READ_ONLY : NONE;
__ push(Immediate(Smi::FromInt(attr)));
} else {
__ push(Immediate(Smi::FromInt(0))); // Indicates no initial value.
}
- __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
+ __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
break;
}
}
case Variable::UNALLOCATED: {
globals_->Add(variable->name(), zone());
Handle<SharedFunctionInfo> function =
- Compiler::BuildFunctionInfo(declaration->fun(), script());
+ Compiler::BuildFunctionInfo(declaration->fun(), script(), info_);
// Check for stack-overflow exception.
if (function.is_null()) return SetStackOverflow();
globals_->Add(function, zone());
VisitForAccumulatorValue(declaration->fun());
__ mov(ContextOperand(esi, variable->index()), result_register());
// We know that we have written a function, which is not a smi.
- __ RecordWriteContextSlot(esi,
- Context::SlotOffset(variable->index()),
- result_register(),
- ecx,
- EMIT_REMEMBERED_SET,
- OMIT_SMI_CHECK);
+ __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()),
+ result_register(), ecx, kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
__ push(Immediate(variable->name()));
__ push(Immediate(Smi::FromInt(NONE)));
VisitForStackValue(declaration->fun());
- __ CallRuntime(Runtime::kHiddenDeclareContextSlot, 4);
+ __ CallRuntime(Runtime::kDeclareLookupSlot, 4);
break;
}
}
void FullCodeGenerator::VisitModuleDeclaration(ModuleDeclaration* declaration) {
Variable* variable = declaration->proxy()->var();
- ASSERT(variable->location() == Variable::CONTEXT);
- ASSERT(variable->interface()->IsFrozen());
+ DCHECK(variable->location() == Variable::CONTEXT);
+ DCHECK(variable->interface()->IsFrozen());
Comment cmnt(masm_, "[ ModuleDeclaration");
EmitDebugCheckDeclarationContext(variable);
// Assign it.
__ mov(ContextOperand(esi, variable->index()), eax);
// We know that we have written a module, which is not a smi.
- __ RecordWriteContextSlot(esi,
- Context::SlotOffset(variable->index()),
- eax,
- ecx,
- EMIT_REMEMBERED_SET,
+ __ RecordWriteContextSlot(esi, Context::SlotOffset(variable->index()), eax,
+ ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(declaration->proxy()->id(), NO_REGISTERS);
__ push(esi); // The context is the first argument.
__ Push(pairs);
__ Push(Smi::FromInt(DeclareGlobalsFlags()));
- __ CallRuntime(Runtime::kHiddenDeclareGlobals, 3);
+ __ CallRuntime(Runtime::kDeclareGlobals, 3);
// Return value is ignored.
}
void FullCodeGenerator::DeclareModules(Handle<FixedArray> descriptions) {
// Call the runtime to declare the modules.
__ Push(descriptions);
- __ CallRuntime(Runtime::kHiddenDeclareModules, 1);
+ __ CallRuntime(Runtime::kDeclareModules, 1);
// Return value is ignored.
}
// Record position before stub call for type feedback.
SetSourcePosition(clause->position());
- Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
+ Handle<Code> ic =
+ CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
patch_site.EmitPatchInfo();
// No need for a write barrier, we are storing a Smi in the feedback vector.
__ LoadHeapObject(ebx, FeedbackVector());
__ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
- Immediate(TypeFeedbackInfo::MegamorphicSentinel(isolate())));
+ Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate())));
__ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
__ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
// For proxies, no filtering is done.
// TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
- ASSERT(Smi::FromInt(0) == 0);
+ DCHECK(Smi::FromInt(0) == 0);
__ test(edx, edx);
__ j(zero, &update_each);
Iteration loop_statement(this, stmt);
increment_loop_depth();
- // var iterable = subject
- VisitForAccumulatorValue(stmt->assign_iterable());
-
- // As with for-in, skip the loop if the iterator is null or undefined.
- __ CompareRoot(eax, Heap::kUndefinedValueRootIndex);
- __ j(equal, loop_statement.break_label());
- __ CompareRoot(eax, Heap::kNullValueRootIndex);
- __ j(equal, loop_statement.break_label());
-
// var iterator = iterable[Symbol.iterator]();
VisitForEffect(stmt->assign_iterator());
!pretenure &&
scope()->is_function_scope() &&
info->num_literals() == 0) {
- FastNewClosureStub stub(isolate(),
- info->strict_mode(),
- info->is_generator());
+ FastNewClosureStub stub(isolate(), info->strict_mode(), info->kind());
__ mov(ebx, Immediate(info));
__ CallStub(&stub);
} else {
__ push(Immediate(pretenure
? isolate()->factory()->true_value()
: isolate()->factory()->false_value()));
- __ CallRuntime(Runtime::kHiddenNewClosure, 3);
+ __ CallRuntime(Runtime::kNewClosure, 3);
}
context()->Plug(eax);
}
}
-void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var,
+void FullCodeGenerator::EmitLoadHomeObject(SuperReference* expr) {
+ Comment cnmt(masm_, "[ SuperReference ");
+
+ __ mov(LoadDescriptor::ReceiverRegister(),
+ Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
+
+ Handle<Symbol> home_object_symbol(isolate()->heap()->home_object_symbol());
+ __ mov(LoadDescriptor::NameRegister(), home_object_symbol);
+
+ CallLoadIC(NOT_CONTEXTUAL, expr->HomeObjectFeedbackId());
+
+ __ cmp(eax, isolate()->factory()->undefined_value());
+ Label done;
+ __ j(not_equal, &done);
+ __ CallRuntime(Runtime::kThrowNonMethodError, 0);
+ __ bind(&done);
+}
+
+
+void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
TypeofState typeof_state,
Label* slow) {
Register context = esi;
// All extension objects were empty and it is safe to use a global
// load IC call.
- __ mov(edx, GlobalObjectOperand());
- __ mov(ecx, var->name());
+ __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadDescriptor::NameRegister(), proxy->var()->name());
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ }
+
ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
? NOT_CONTEXTUAL
: CONTEXTUAL;
MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
Label* slow) {
- ASSERT(var->IsContextSlot());
+ DCHECK(var->IsContextSlot());
Register context = esi;
Register temp = ebx;
}
-void FullCodeGenerator::EmitDynamicLookupFastCase(Variable* var,
+void FullCodeGenerator::EmitDynamicLookupFastCase(VariableProxy* proxy,
TypeofState typeof_state,
Label* slow,
Label* done) {
// introducing variables. In those cases, we do not want to
// perform a runtime call for all variables in the scope
// containing the eval.
+ Variable* var = proxy->var();
if (var->mode() == DYNAMIC_GLOBAL) {
- EmitLoadGlobalCheckExtensions(var, typeof_state, slow);
+ EmitLoadGlobalCheckExtensions(proxy, typeof_state, slow);
__ jmp(done);
} else if (var->mode() == DYNAMIC_LOCAL) {
Variable* local = var->local_if_not_shadowed();
__ mov(eax, isolate()->factory()->undefined_value());
} else { // LET || CONST
__ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
}
}
__ jmp(done);
switch (var->location()) {
case Variable::UNALLOCATED: {
Comment cmnt(masm_, "[ Global variable");
- // Use inline caching. Variable name is passed in ecx and the global
- // object in eax.
- __ mov(edx, GlobalObjectOperand());
- __ mov(ecx, var->name());
+ __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadDescriptor::NameRegister(), var->name());
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ }
CallLoadIC(CONTEXTUAL);
context()->Plug(eax);
break;
// always looked up dynamically, i.e. in that case
// var->location() == LOOKUP.
// always holds.
- ASSERT(var->scope() != NULL);
+ DCHECK(var->scope() != NULL);
// Check if the binding really needs an initialization check. The check
// can be skipped in the following situation: we have a LET or CONST
skip_init_check = false;
} else {
// Check that we always have valid source position.
- ASSERT(var->initializer_position() != RelocInfo::kNoPosition);
- ASSERT(proxy->position() != RelocInfo::kNoPosition);
+ DCHECK(var->initializer_position() != RelocInfo::kNoPosition);
+ DCHECK(proxy->position() != RelocInfo::kNoPosition);
skip_init_check = var->mode() != CONST_LEGACY &&
var->initializer_position() < proxy->position();
}
// Throw a reference error when using an uninitialized let/const
// binding in harmony mode.
__ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
} else {
// Uninitalized const bindings outside of harmony mode are unholed.
- ASSERT(var->mode() == CONST_LEGACY);
+ DCHECK(var->mode() == CONST_LEGACY);
__ mov(eax, isolate()->factory()->undefined_value());
}
__ bind(&done);
Label done, slow;
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
__ push(esi); // Context.
__ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
+ __ CallRuntime(Runtime::kLoadLookupSlot, 2);
__ bind(&done);
context()->Plug(eax);
break;
__ push(Immediate(Smi::FromInt(expr->literal_index())));
__ push(Immediate(expr->pattern()));
__ push(Immediate(expr->flags()));
- __ CallRuntime(Runtime::kHiddenMaterializeRegExpLiteral, 4);
+ __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
__ mov(ebx, eax);
__ bind(&materialized);
__ bind(&runtime_allocate);
__ push(ebx);
__ push(Immediate(Smi::FromInt(size)));
- __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
__ pop(ebx);
__ bind(&allocated);
__ push(Immediate(Smi::FromInt(expr->literal_index())));
__ push(Immediate(constant_properties));
__ push(Immediate(Smi::FromInt(flags)));
- __ CallRuntime(Runtime::kHiddenCreateObjectLiteral, 4);
+ __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
} else {
__ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ mov(eax, FieldOperand(edi, JSFunction::kLiteralsOffset));
case ObjectLiteral::Property::CONSTANT:
UNREACHABLE();
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
- ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
+ DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
// Fall through.
case ObjectLiteral::Property::COMPUTED:
if (key->value()->IsInternalizedString()) {
if (property->emit_store()) {
VisitForAccumulatorValue(value);
- __ mov(ecx, Immediate(key->value()));
- __ mov(edx, Operand(esp, 0));
+ DCHECK(StoreDescriptor::ValueRegister().is(eax));
+ __ mov(StoreDescriptor::NameRegister(), Immediate(key->value()));
+ __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
CallStoreIC(key->LiteralFeedbackId());
PrepareForBailoutForId(key->id(), NO_REGISTERS);
} else {
VisitForStackValue(key);
VisitForStackValue(value);
if (property->emit_store()) {
- __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
+ __ push(Immediate(Smi::FromInt(SLOPPY))); // Strict mode
__ CallRuntime(Runtime::kSetProperty, 4);
} else {
__ Drop(3);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ push(Immediate(Smi::FromInt(NONE)));
- __ CallRuntime(Runtime::kDefineOrRedefineAccessorProperty, 5);
+ __ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
}
if (expr->has_function()) {
- ASSERT(result_saved);
+ DCHECK(result_saved);
__ push(Operand(esp, 0));
__ CallRuntime(Runtime::kToFastProperties, 1);
}
ZoneList<Expression*>* subexprs = expr->values();
int length = subexprs->length();
Handle<FixedArray> constant_elements = expr->constant_elements();
- ASSERT_EQ(2, constant_elements->length());
+ DCHECK_EQ(2, constant_elements->length());
ElementsKind constant_elements_kind =
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
bool has_constant_fast_elements =
__ push(Immediate(Smi::FromInt(expr->literal_index())));
__ push(Immediate(constant_elements));
__ push(Immediate(Smi::FromInt(flags)));
- __ CallRuntime(Runtime::kHiddenCreateArrayLiteral, 4);
+ __ CallRuntime(Runtime::kCreateArrayLiteral, 4);
} else {
__ mov(ebx, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
__ mov(eax, FieldOperand(ebx, JSFunction::kLiteralsOffset));
// Store the subexpression value in the array's elements.
__ mov(FieldOperand(ebx, offset), result_register());
// Update the write barrier for the array store.
- __ RecordWriteField(ebx, offset, result_register(), ecx,
- EMIT_REMEMBERED_SET,
- INLINE_SMI_CHECK);
+ __ RecordWriteField(ebx, offset, result_register(), ecx, kDontSaveFPRegs,
+ EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
} else {
// Store the subexpression value in the array's elements.
__ mov(ecx, Immediate(Smi::FromInt(i)));
void FullCodeGenerator::VisitAssignment(Assignment* expr) {
- ASSERT(expr->target()->IsValidReferenceExpression());
+ DCHECK(expr->target()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ Assignment");
break;
case NAMED_PROPERTY:
if (expr->is_compound()) {
- // We need the receiver both on the stack and in edx.
+ // We need the receiver both on the stack and in the register.
VisitForStackValue(property->obj());
- __ mov(edx, Operand(esp, 0));
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
} else {
VisitForStackValue(property->obj());
}
if (expr->is_compound()) {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
- __ mov(edx, Operand(esp, kPointerSize)); // Object.
- __ mov(ecx, Operand(esp, 0)); // Key.
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, kPointerSize));
+ __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0));
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
VisitForStackValue(expr->expression());
switch (expr->yield_kind()) {
- case Yield::SUSPEND:
+ case Yield::kSuspend:
// Pop value from top-of-stack slot; box result into result register.
EmitCreateIteratorResult(false);
__ push(result_register());
// Fall through.
- case Yield::INITIAL: {
+ case Yield::kInitial: {
Label suspend, continuation, post_runtime, resume;
__ jmp(&suspend);
__ bind(&suspend);
VisitForAccumulatorValue(expr->generator_object());
- ASSERT(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
+ DCHECK(continuation.pos() > 0 && Smi::IsValid(continuation.pos()));
__ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
Immediate(Smi::FromInt(continuation.pos())));
__ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
__ mov(ecx, esi);
- __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx);
+ __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
+ kDontSaveFPRegs);
__ lea(ebx, Operand(ebp, StandardFrameConstants::kExpressionsOffset));
__ cmp(esp, ebx);
__ j(equal, &post_runtime);
__ push(eax); // generator object
- __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
+ __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ bind(&post_runtime);
break;
}
- case Yield::FINAL: {
+ case Yield::kFinal: {
VisitForAccumulatorValue(expr->generator_object());
__ mov(FieldOperand(result_register(),
JSGeneratorObject::kContinuationOffset),
break;
}
- case Yield::DELEGATING: {
+ case Yield::kDelegating: {
VisitForStackValue(expr->generator_object());
// Initial stack layout is as follows:
Label l_catch, l_try, l_suspend, l_continuation, l_resume;
Label l_next, l_call, l_loop;
+ Register load_receiver = LoadDescriptor::ReceiverRegister();
+ Register load_name = LoadDescriptor::NameRegister();
+
// Initial send value is undefined.
__ mov(eax, isolate()->factory()->undefined_value());
__ jmp(&l_next);
// catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
__ bind(&l_catch);
handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
- __ mov(ecx, isolate()->factory()->throw_string()); // "throw"
- __ push(ecx); // "throw"
- __ push(Operand(esp, 2 * kPointerSize)); // iter
- __ push(eax); // exception
+ __ mov(load_name, isolate()->factory()->throw_string()); // "throw"
+ __ push(load_name); // "throw"
+ __ push(Operand(esp, 2 * kPointerSize)); // iter
+ __ push(eax); // exception
__ jmp(&l_call);
// try { received = %yield result }
const int generator_object_depth = kPointerSize + handler_size;
__ mov(eax, Operand(esp, generator_object_depth));
__ push(eax); // g
- ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
+ DCHECK(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
__ mov(FieldOperand(eax, JSGeneratorObject::kContinuationOffset),
Immediate(Smi::FromInt(l_continuation.pos())));
__ mov(FieldOperand(eax, JSGeneratorObject::kContextOffset), esi);
__ mov(ecx, esi);
- __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx);
- __ CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject, 1);
+ __ RecordWriteField(eax, JSGeneratorObject::kContextOffset, ecx, edx,
+ kDontSaveFPRegs);
+ __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ pop(eax); // result
// receiver = iter; f = iter.next; arg = received;
__ bind(&l_next);
- __ mov(ecx, isolate()->factory()->next_string()); // "next"
- __ push(ecx);
- __ push(Operand(esp, 2 * kPointerSize)); // iter
- __ push(eax); // received
+
+ __ mov(load_name, isolate()->factory()->next_string());
+ __ push(load_name); // "next"
+ __ push(Operand(esp, 2 * kPointerSize)); // iter
+ __ push(eax); // received
// result = receiver[f](arg);
__ bind(&l_call);
- __ mov(edx, Operand(esp, kPointerSize));
- Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
+ __ mov(load_receiver, Operand(esp, kPointerSize));
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(expr->KeyedLoadFeedbackSlot())));
+ }
+ Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
CallIC(ic, TypeFeedbackId::None());
__ mov(edi, eax);
__ mov(Operand(esp, 2 * kPointerSize), edi);
// if (!result.done) goto l_try;
__ bind(&l_loop);
__ push(eax); // save result
- __ mov(edx, eax); // result
- __ mov(ecx, isolate()->factory()->done_string()); // "done"
+ __ Move(load_receiver, eax); // result
+ __ mov(load_name,
+ isolate()->factory()->done_string()); // "done"
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(expr->DoneFeedbackSlot())));
+ }
CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
CallIC(bool_ic);
__ j(zero, &l_try);
// result.value
- __ pop(edx); // result
- __ mov(ecx, isolate()->factory()->value_string()); // "value"
+ __ pop(load_receiver); // result
+ __ mov(load_name,
+ isolate()->factory()->value_string()); // "value"
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(expr->ValueFeedbackSlot())));
+ }
CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
context()->DropAndPlug(2, eax); // drop iter and g
break;
Expression *value,
JSGeneratorObject::ResumeMode resume_mode) {
// The value stays in eax, and is ultimately read by the resumed generator, as
- // if CallRuntime(Runtime::kHiddenSuspendJSGeneratorObject) returned it. Or it
+ // if CallRuntime(Runtime::kSuspendJSGeneratorObject) returned it. Or it
// is read to throw the value when the resumed generator is already closed.
// ebx will hold the generator object until the activation has been resumed.
VisitForStackValue(generator);
__ push(ebx);
__ push(result_register());
__ Push(Smi::FromInt(resume_mode));
- __ CallRuntime(Runtime::kHiddenResumeJSGeneratorObject, 3);
+ __ CallRuntime(Runtime::kResumeJSGeneratorObject, 3);
// Not reached: the runtime call returns elsewhere.
__ Abort(kGeneratorFailedToResume);
} else {
// Throw the provided value.
__ push(eax);
- __ CallRuntime(Runtime::kHiddenThrow, 1);
+ __ CallRuntime(Runtime::kThrow, 1);
}
__ jmp(&done);
// Throw error if we attempt to operate on a running generator.
__ bind(&wrong_state);
__ push(ebx);
- __ CallRuntime(Runtime::kHiddenThrowGeneratorStateError, 1);
+ __ CallRuntime(Runtime::kThrowGeneratorStateError, 1);
__ bind(&done);
context()->Plug(result_register());
Label gc_required;
Label allocated;
- Handle<Map> map(isolate()->native_context()->iterator_result_map());
+ const int instance_size = 5 * kPointerSize;
+ DCHECK_EQ(isolate()->native_context()->iterator_result_map()->instance_size(),
+ instance_size);
- __ Allocate(map->instance_size(), eax, ecx, edx, &gc_required, TAG_OBJECT);
+ __ Allocate(instance_size, eax, ecx, edx, &gc_required, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&gc_required);
- __ Push(Smi::FromInt(map->instance_size()));
- __ CallRuntime(Runtime::kHiddenAllocateInNewSpace, 1);
+ __ Push(Smi::FromInt(instance_size));
+ __ CallRuntime(Runtime::kAllocateInNewSpace, 1);
__ mov(context_register(),
Operand(ebp, StandardFrameConstants::kContextOffset));
__ bind(&allocated);
- __ mov(ebx, map);
+ __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
+ __ mov(ebx, FieldOperand(ebx, GlobalObject::kNativeContextOffset));
+ __ mov(ebx, ContextOperand(ebx, Context::ITERATOR_RESULT_MAP_INDEX));
__ pop(ecx);
__ mov(edx, isolate()->factory()->ToBoolean(done));
- ASSERT_EQ(map->instance_size(), 5 * kPointerSize);
__ mov(FieldOperand(eax, HeapObject::kMapOffset), ebx);
__ mov(FieldOperand(eax, JSObject::kPropertiesOffset),
isolate()->factory()->empty_fixed_array());
// Only the value field needs a write barrier, as the other values are in the
// root set.
- __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset,
- ecx, edx);
+ __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, ecx,
+ edx, kDontSaveFPRegs);
}
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
- ASSERT(!key->value()->IsSmi());
- __ mov(ecx, Immediate(key->value()));
- CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
+ DCHECK(!key->value()->IsSmi());
+ __ mov(LoadDescriptor::NameRegister(), Immediate(key->value()));
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
+ CallLoadIC(NOT_CONTEXTUAL);
+ } else {
+ CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
+ }
+}
+
+
+void FullCodeGenerator::EmitNamedSuperPropertyLoad(Property* prop) {
+ SetSourcePosition(prop->position());
+ Literal* key = prop->key()->AsLiteral();
+ DCHECK(!key->value()->IsSmi());
+ DCHECK(prop->IsSuperAccess());
+
+ SuperReference* super_ref = prop->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ push(eax);
+ VisitForStackValue(super_ref->this_var());
+ __ push(Immediate(key->value()));
+ __ CallRuntime(Runtime::kLoadFromSuper, 3);
}
void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
- Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
- CallIC(ic, prop->PropertyFeedbackId());
+ Handle<Code> ic = CodeFactory::KeyedLoadIC(isolate()).code();
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(prop->PropertyFeedbackSlot())));
+ CallIC(ic);
+ } else {
+ CallIC(ic, prop->PropertyFeedbackId());
+ }
}
__ bind(&stub_call);
__ mov(eax, ecx);
- BinaryOpICStub stub(isolate(), op, mode);
- CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
+ CallIC(code, expr->BinaryOperationFeedbackId());
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
Token::Value op,
OverwriteMode mode) {
__ pop(edx);
- BinaryOpICStub stub(isolate(), op, mode);
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op, mode).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
- CallIC(stub.GetCode(), expr->BinaryOperationFeedbackId());
+ CallIC(code, expr->BinaryOperationFeedbackId());
patch_site.EmitPatchInfo();
context()->Plug(eax);
}
void FullCodeGenerator::EmitAssignment(Expression* expr) {
- ASSERT(expr->IsValidReferenceExpression());
+ DCHECK(expr->IsValidReferenceExpression());
// Left-hand side can only be a property, a global or a (parameter or local)
// slot.
case NAMED_PROPERTY: {
__ push(eax); // Preserve value.
VisitForAccumulatorValue(prop->obj());
- __ mov(edx, eax);
- __ pop(eax); // Restore value.
- __ mov(ecx, prop->key()->AsLiteral()->value());
+ __ Move(StoreDescriptor::ReceiverRegister(), eax);
+ __ pop(StoreDescriptor::ValueRegister()); // Restore value.
+ __ mov(StoreDescriptor::NameRegister(),
+ prop->key()->AsLiteral()->value());
CallStoreIC();
break;
}
__ push(eax); // Preserve value.
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
- __ mov(ecx, eax);
- __ pop(edx); // Receiver.
- __ pop(eax); // Restore value.
- Handle<Code> ic = strict_mode() == SLOPPY
- ? isolate()->builtins()->KeyedStoreIC_Initialize()
- : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
+ __ Move(StoreDescriptor::NameRegister(), eax);
+ __ pop(StoreDescriptor::ReceiverRegister()); // Receiver.
+ __ pop(StoreDescriptor::ValueRegister()); // Restore value.
+ Handle<Code> ic =
+ CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
CallIC(ic);
break;
}
if (var->IsContextSlot()) {
__ mov(edx, eax);
int offset = Context::SlotOffset(var->index());
- __ RecordWriteContextSlot(ecx, offset, edx, ebx);
+ __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
}
}
-void FullCodeGenerator::EmitCallStoreContextSlot(
- Handle<String> name, StrictMode strict_mode) {
- __ push(eax); // Value.
- __ push(esi); // Context.
- __ push(Immediate(name));
- __ push(Immediate(Smi::FromInt(strict_mode)));
- __ CallRuntime(Runtime::kHiddenStoreContextSlot, 4);
-}
-
-
void FullCodeGenerator::EmitVariableAssignment(Variable* var,
Token::Value op) {
if (var->IsUnallocated()) {
// Global var, const, or let.
- __ mov(ecx, var->name());
- __ mov(edx, GlobalObjectOperand());
+ __ mov(StoreDescriptor::NameRegister(), var->name());
+ __ mov(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
CallStoreIC();
} else if (op == Token::INIT_CONST_LEGACY) {
// Const initializers need a write barrier.
- ASSERT(!var->IsParameter()); // No const parameters.
+ DCHECK(!var->IsParameter()); // No const parameters.
if (var->IsLookupSlot()) {
__ push(eax);
__ push(esi);
__ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenInitializeConstContextSlot, 3);
+ __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, 3);
} else {
- ASSERT(var->IsStackLocal() || var->IsContextSlot());
+ DCHECK(var->IsStackLocal() || var->IsContextSlot());
Label skip;
MemOperand location = VarOperand(var, ecx);
__ mov(edx, location);
} 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(), strict_mode());
- } else {
- ASSERT(var->IsStackAllocated() || var->IsContextSlot());
- Label assign;
- MemOperand location = VarOperand(var, ecx);
- __ mov(edx, location);
- __ cmp(edx, isolate()->factory()->the_hole_value());
- __ j(not_equal, &assign, Label::kNear);
- __ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenThrowReferenceError, 1);
- __ bind(&assign);
- EmitStoreToStackLocalOrContextSlot(var, location);
- }
+ DCHECK(!var->IsLookupSlot());
+ DCHECK(var->IsStackAllocated() || var->IsContextSlot());
+ Label assign;
+ MemOperand location = VarOperand(var, ecx);
+ __ mov(edx, location);
+ __ cmp(edx, isolate()->factory()->the_hole_value());
+ __ j(not_equal, &assign, Label::kNear);
+ __ push(Immediate(var->name()));
+ __ CallRuntime(Runtime::kThrowReferenceError, 1);
+ __ bind(&assign);
+ EmitStoreToStackLocalOrContextSlot(var, location);
} else if (!var->is_const_mode() || op == Token::INIT_CONST) {
- // Assignment to var or initializing assignment to let/const
- // in harmony mode.
if (var->IsLookupSlot()) {
- EmitCallStoreContextSlot(var->name(), strict_mode());
+ // Assignment to var.
+ __ push(eax); // Value.
+ __ push(esi); // Context.
+ __ push(Immediate(var->name()));
+ __ push(Immediate(Smi::FromInt(strict_mode())));
+ __ CallRuntime(Runtime::kStoreLookupSlot, 4);
} else {
- ASSERT(var->IsStackAllocated() || var->IsContextSlot());
+ // Assignment to var or initializing assignment to let/const in harmony
+ // mode.
+ DCHECK(var->IsStackAllocated() || var->IsContextSlot());
MemOperand location = VarOperand(var, ecx);
if (generate_debug_code_ && op == Token::INIT_LET) {
// Check for an uninitialized let binding.
// esp[0] : receiver
Property* prop = expr->target()->AsProperty();
- ASSERT(prop != NULL);
- ASSERT(prop->key()->IsLiteral());
+ DCHECK(prop != NULL);
+ DCHECK(prop->key()->IsLiteral());
// Record source code position before IC call.
SetSourcePosition(expr->position());
- __ mov(ecx, prop->key()->AsLiteral()->value());
- __ pop(edx);
+ __ mov(StoreDescriptor::NameRegister(), prop->key()->AsLiteral()->value());
+ __ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->AssignmentFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
// esp[0] : key
// esp[kPointerSize] : receiver
- __ pop(ecx); // Key.
- __ pop(edx);
+ __ pop(StoreDescriptor::NameRegister()); // Key.
+ __ pop(StoreDescriptor::ReceiverRegister());
+ DCHECK(StoreDescriptor::ValueRegister().is(eax));
// Record source code position before IC call.
SetSourcePosition(expr->position());
- Handle<Code> ic = strict_mode() == SLOPPY
- ? isolate()->builtins()->KeyedStoreIC_Initialize()
- : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
+ Handle<Code> ic = CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
CallIC(ic, expr->AssignmentFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
Expression* key = expr->key();
if (key->IsPropertyName()) {
- VisitForAccumulatorValue(expr->obj());
- __ mov(edx, result_register());
- EmitNamedPropertyLoad(expr);
+ if (!expr->IsSuperAccess()) {
+ VisitForAccumulatorValue(expr->obj());
+ __ Move(LoadDescriptor::ReceiverRegister(), result_register());
+ EmitNamedPropertyLoad(expr);
+ } else {
+ EmitNamedSuperPropertyLoad(expr);
+ }
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(eax);
} else {
VisitForStackValue(expr->obj());
VisitForAccumulatorValue(expr->key());
- __ pop(edx); // Object.
- __ mov(ecx, result_register()); // Key.
+ __ pop(LoadDescriptor::ReceiverRegister()); // Object.
+ __ Move(LoadDescriptor::NameRegister(), result_register()); // Key.
EmitKeyedPropertyLoad(expr);
context()->Plug(eax);
}
void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
Expression* callee = expr->expression();
- CallIC::CallType call_type = callee->IsVariableProxy()
- ? CallIC::FUNCTION
- : CallIC::METHOD;
+ CallICState::CallType call_type =
+ callee->IsVariableProxy() ? CallICState::FUNCTION : CallICState::METHOD;
// Get the target function.
- if (call_type == CallIC::FUNCTION) {
+ if (call_type == CallICState::FUNCTION) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, NO_REGISTERS);
__ push(Immediate(isolate()->factory()->undefined_value()));
} else {
// Load the function from the receiver.
- ASSERT(callee->IsProperty());
- __ mov(edx, Operand(esp, 0));
+ DCHECK(callee->IsProperty());
+ DCHECK(!callee->AsProperty()->IsSuperAccess());
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
}
+void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
+ Expression* callee = expr->expression();
+ DCHECK(callee->IsProperty());
+ Property* prop = callee->AsProperty();
+ DCHECK(prop->IsSuperAccess());
+
+ SetSourcePosition(prop->position());
+ Literal* key = prop->key()->AsLiteral();
+ DCHECK(!key->value()->IsSmi());
+ // Load the function from the receiver.
+ SuperReference* super_ref = callee->AsProperty()->obj()->AsSuperReference();
+ EmitLoadHomeObject(super_ref);
+ __ push(eax);
+ VisitForAccumulatorValue(super_ref->this_var());
+ __ push(eax);
+ __ push(Operand(esp, kPointerSize));
+ __ push(eax);
+ __ push(Immediate(key->value()));
+ // Stack here:
+ // - home_object
+ // - this (receiver)
+ // - home_object <-- LoadFromSuper will pop here and below.
+ // - this (receiver)
+ // - key
+ __ CallRuntime(Runtime::kLoadFromSuper, 3);
+
+ // Replace home_object with target function.
+ __ mov(Operand(esp, kPointerSize), eax);
+
+ // Stack here:
+ // - target function
+ // - this (receiver)
+ EmitCall(expr, CallICState::METHOD);
+}
+
+
// Code common for calls using the IC.
void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
Expression* key) {
Expression* callee = expr->expression();
// Load the function from the receiver.
- ASSERT(callee->IsProperty());
- __ mov(edx, Operand(esp, 0));
- // Move the key into the right register for the keyed load IC.
- __ mov(ecx, eax);
+ DCHECK(callee->IsProperty());
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
+ __ mov(LoadDescriptor::NameRegister(), eax);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
__ push(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
- EmitCall(expr, CallIC::METHOD);
+ EmitCall(expr, CallICState::METHOD);
}
-void FullCodeGenerator::EmitCall(Call* expr, CallIC::CallType call_type) {
+void FullCodeGenerator::EmitCall(Call* expr, CallICState::CallType call_type) {
// Load the arguments.
ZoneList<Expression*>* args = expr->arguments();
int arg_count = args->length();
__ push(Immediate(isolate()->factory()->undefined_value()));
}
+ // Push the enclosing function.
+ __ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
// Push the receiver of the enclosing function.
__ push(Operand(ebp, (2 + info_->scope()->num_parameters()) * kPointerSize));
// Push the language mode.
__ push(Immediate(Smi::FromInt(scope()->start_position())));
// Do the runtime call.
- __ CallRuntime(Runtime::kHiddenResolvePossiblyDirectEval, 5);
+ __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
}
{ PreservePositionScope scope(masm()->positions_recorder());
// Generate code for loading from variables potentially shadowed by
// eval-introduced variables.
- EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy, NOT_INSIDE_TYPEOF, &slow, &done);
}
__ bind(&slow);
// Call the runtime to find the function to call (returned in eax) and
// the object holding it (returned in edx).
__ push(context_register());
__ push(Immediate(proxy->name()));
- __ CallRuntime(Runtime::kHiddenLoadContextSlot, 2);
+ __ CallRuntime(Runtime::kLoadLookupSlot, 2);
__ push(eax); // Function.
__ push(edx); // Receiver.
} else if (call_type == Call::PROPERTY_CALL) {
Property* property = callee->AsProperty();
- { PreservePositionScope scope(masm()->positions_recorder());
- VisitForStackValue(property->obj());
- }
- if (property->key()->IsPropertyName()) {
- EmitCallWithLoadIC(expr);
+ bool is_named_call = property->key()->IsPropertyName();
+ // super.x() is handled in EmitCallWithLoadIC.
+ if (property->IsSuperAccess() && is_named_call) {
+ EmitSuperCallWithLoadIC(expr);
} else {
- EmitKeyedCallWithLoadIC(expr, property->key());
+ {
+ PreservePositionScope scope(masm()->positions_recorder());
+ VisitForStackValue(property->obj());
+ }
+ if (is_named_call) {
+ EmitCallWithLoadIC(expr);
+ } else {
+ EmitKeyedCallWithLoadIC(expr, property->key());
+ }
}
-
} else {
- ASSERT(call_type == Call::OTHER_CALL);
+ DCHECK(call_type == Call::OTHER_CALL);
// Call to an arbitrary expression not handled specially above.
{ PreservePositionScope scope(masm()->positions_recorder());
VisitForStackValue(callee);
#ifdef DEBUG
// RecordJSReturnSite should have been called.
- ASSERT(expr->return_is_recorded_);
+ DCHECK(expr->return_is_recorded_);
#endif
}
// Record call targets in unoptimized code.
if (FLAG_pretenuring_call_new) {
EnsureSlotContainsAllocationSite(expr->AllocationSiteFeedbackSlot());
- ASSERT(expr->AllocationSiteFeedbackSlot() ==
+ DCHECK(expr->AllocationSiteFeedbackSlot() ==
expr->CallNewFeedbackSlot() + 1);
}
void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsNonNegativeSmi(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsSpecObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsUndetectableObject(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsMinusZero(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsArray(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsRegExp(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitIsConstructCall(CallRuntime* expr) {
- ASSERT(expr->arguments()->length() == 0);
+ DCHECK(expr->arguments()->length() == 0);
Label materialize_true, materialize_false;
Label* if_true = NULL;
void FullCodeGenerator::EmitObjectEquals(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
+ DCHECK(args->length() == 2);
// Load the two objects into registers and perform the comparison.
VisitForStackValue(args->at(0));
void FullCodeGenerator::EmitArguments(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
// ArgumentsAccessStub expects the key in edx and the formal
// parameter count in eax.
void FullCodeGenerator::EmitArgumentsLength(CallRuntime* expr) {
- ASSERT(expr->arguments()->length() == 0);
+ DCHECK(expr->arguments()->length() == 0);
Label exit;
// Get the number of formal parameters.
void FullCodeGenerator::EmitClassOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
Label done, null, function, non_function_constructor;
VisitForAccumulatorValue(args->at(0));
// Functions have class 'Function'.
__ bind(&function);
- __ mov(eax, isolate()->factory()->function_class_string());
+ __ mov(eax, isolate()->factory()->Function_string());
__ jmp(&done);
// Objects with a non-function constructor have class 'Object'.
// Load the arguments on the stack and call the stub.
SubStringStub stub(isolate());
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 3);
+ DCHECK(args->length() == 3);
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
VisitForStackValue(args->at(2));
// Load the arguments on the stack and call the stub.
RegExpExecStub stub(isolate());
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 4);
+ DCHECK(args->length() == 4);
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
VisitForStackValue(args->at(2));
void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0)); // Load the object.
void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
- ASSERT_NE(NULL, args->at(1)->AsLiteral());
+ DCHECK(args->length() == 2);
+ DCHECK_NE(NULL, args->at(1)->AsLiteral());
Smi* index = Smi::cast(*(args->at(1)->AsLiteral()->value()));
VisitForAccumulatorValue(args->at(0)); // Load the object.
}
__ bind(¬_date_object);
- __ CallRuntime(Runtime::kHiddenThrowNotDateError, 0);
+ __ CallRuntime(Runtime::kThrowNotDateError, 0);
__ bind(&done);
context()->Plug(result);
}
void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT_EQ(3, args->length());
+ DCHECK_EQ(3, args->length());
Register string = eax;
Register index = ebx;
Register value = ecx;
- VisitForStackValue(args->at(1)); // index
- VisitForStackValue(args->at(2)); // value
- VisitForAccumulatorValue(args->at(0)); // string
+ VisitForStackValue(args->at(0)); // index
+ VisitForStackValue(args->at(1)); // value
+ VisitForAccumulatorValue(args->at(2)); // string
__ pop(value);
__ pop(index);
void FullCodeGenerator::EmitTwoByteSeqStringSetChar(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT_EQ(3, args->length());
+ DCHECK_EQ(3, args->length());
Register string = eax;
Register index = ebx;
Register value = ecx;
- VisitForStackValue(args->at(1)); // index
- VisitForStackValue(args->at(2)); // value
- VisitForAccumulatorValue(args->at(0)); // string
+ VisitForStackValue(args->at(0)); // index
+ VisitForStackValue(args->at(1)); // value
+ VisitForAccumulatorValue(args->at(2)); // string
__ pop(value);
__ pop(index);
void FullCodeGenerator::EmitMathPow(CallRuntime* expr) {
// Load the arguments on the stack and call the runtime function.
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
+ DCHECK(args->length() == 2);
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
- __ CallRuntime(Runtime::kHiddenMathPowSlow, 2);
+ __ CallRuntime(Runtime::kMathPowSlow, 2);
context()->Plug(eax);
}
void FullCodeGenerator::EmitSetValueOf(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
+ DCHECK(args->length() == 2);
VisitForStackValue(args->at(0)); // Load the object.
VisitForAccumulatorValue(args->at(1)); // Load the value.
// Update the write barrier. Save the value as it will be
// overwritten by the write barrier code and is needed afterward.
__ mov(edx, eax);
- __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx);
+ __ RecordWriteField(ebx, JSValue::kValueOffset, edx, ecx, kDontSaveFPRegs);
__ bind(&done);
context()->Plug(eax);
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT_EQ(args->length(), 1);
+ DCHECK_EQ(args->length(), 1);
// Load the argument into eax and call the stub.
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitStringCharFromCode(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitStringCharCodeAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
+ DCHECK(args->length() == 2);
VisitForStackValue(args->at(0));
VisitForAccumulatorValue(args->at(1));
void FullCodeGenerator::EmitStringCharAt(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
+ DCHECK(args->length() == 2);
VisitForStackValue(args->at(0));
VisitForAccumulatorValue(args->at(1));
void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT_EQ(2, args->length());
+ DCHECK_EQ(2, args->length());
VisitForStackValue(args->at(0));
VisitForAccumulatorValue(args->at(1));
void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT_EQ(2, args->length());
+ DCHECK_EQ(2, args->length());
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
void FullCodeGenerator::EmitCallFunction(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() >= 2);
+ DCHECK(args->length() >= 2);
int arg_count = args->length() - 2; // 2 ~ receiver and function.
for (int i = 0; i < arg_count + 1; ++i) {
// Load the arguments on the stack and call the stub.
RegExpConstructResultStub stub(isolate());
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 3);
+ DCHECK(args->length() == 3);
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
VisitForAccumulatorValue(args->at(2));
void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT_EQ(2, args->length());
+ DCHECK_EQ(2, args->length());
- ASSERT_NE(NULL, args->at(0)->AsLiteral());
+ DCHECK_NE(NULL, args->at(0)->AsLiteral());
int cache_id = Smi::cast(*(args->at(0)->AsLiteral()->value()))->value();
Handle<FixedArray> jsfunction_result_caches(
// Call runtime to perform the lookup.
__ push(cache);
__ push(key);
- __ CallRuntime(Runtime::kHiddenGetFromCache, 2);
+ __ CallRuntime(Runtime::kGetFromCache, 2);
__ bind(&done);
context()->Plug(eax);
void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 1);
+ DCHECK(args->length() == 1);
VisitForAccumulatorValue(args->at(0));
__ AssertString(eax);
}
-void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
+void FullCodeGenerator::EmitFastOneByteArrayJoin(CallRuntime* expr) {
Label bailout, done, one_char_separator, long_separator,
non_trivial_array, not_size_one_array, loop,
loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
ZoneList<Expression*>* args = expr->arguments();
- ASSERT(args->length() == 2);
+ DCHECK(args->length() == 2);
// We will leave the separator on the stack until the end of the function.
VisitForStackValue(args->at(1));
// Load this to eax (= array)
array = no_reg;
- // Check that all array elements are sequential ASCII strings, and
+ // Check that all array elements are sequential one-byte strings, and
// accumulate the sum of their lengths, as a smi-encoded value.
__ Move(index, Immediate(0));
__ Move(string_length, Immediate(0));
// scratch, string_length, elements.
if (generate_debug_code_) {
__ cmp(index, array_length);
- __ Assert(less, kNoEmptyArraysHereInEmitFastAsciiArrayJoin);
+ __ Assert(less, kNoEmptyArraysHereInEmitFastOneByteArrayJoin);
}
__ bind(&loop);
__ mov(string, FieldOperand(elements,
// string_length: Sum of string lengths, as a smi.
// elements: FixedArray of strings.
- // Check that the separator is a flat ASCII string.
+ // Check that the separator is a flat one-byte string.
__ mov(string, separator_operand);
__ JumpIfSmi(string, &bailout);
__ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
// Live registers and stack values:
// string_length
// elements
- __ AllocateAsciiString(result_pos, string_length, scratch,
- index, string, &bailout);
+ __ AllocateOneByteString(result_pos, string_length, scratch, index, string,
+ &bailout);
__ mov(result_operand, result_pos);
__ lea(result_pos, FieldOperand(result_pos, SeqOneByteString::kHeaderSize));
// One-character separator case
__ bind(&one_char_separator);
- // Replace separator with its ASCII character value.
+ // Replace separator with its one-byte character value.
__ mov_b(scratch, FieldOperand(string, SeqOneByteString::kHeaderSize));
__ mov_b(separator_operand, scratch);
}
+void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) {
+ DCHECK(expr->arguments()->length() == 0);
+ ExternalReference debug_is_active =
+ ExternalReference::debug_is_active_address(isolate());
+ __ movzx_b(eax, Operand::StaticVariable(debug_is_active));
+ __ SmiTag(eax);
+ context()->Plug(eax);
+}
+
+
void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
if (expr->function() != NULL &&
expr->function()->intrinsic_type == Runtime::INLINE) {
__ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
// Load the function from the receiver.
- __ mov(edx, Operand(esp, 0));
- __ mov(ecx, Immediate(expr->name()));
- CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
+ __ mov(LoadDescriptor::NameRegister(), Immediate(expr->name()));
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(expr->CallRuntimeFeedbackSlot())));
+ CallLoadIC(NOT_CONTEXTUAL);
+ } else {
+ CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
+ }
// Push the target function under the receiver.
__ push(Operand(esp, 0));
Variable* var = proxy->var();
// Delete of an unqualified identifier is disallowed in strict mode
// but "delete this" is allowed.
- ASSERT(strict_mode() == SLOPPY || var->is_this());
+ DCHECK(strict_mode() == SLOPPY || var->is_this());
if (var->IsUnallocated()) {
__ push(GlobalObjectOperand());
__ push(Immediate(var->name()));
// context where the variable was introduced.
__ push(context_register());
__ push(Immediate(var->name()));
- __ CallRuntime(Runtime::kHiddenDeleteContextSlot, 2);
+ __ CallRuntime(Runtime::kDeleteLookupSlot, 2);
context()->Plug(eax);
}
} else {
// for control and plugging the control flow into the context,
// because we need to prepare a pair of extra administrative AST ids
// for the optimizing compiler.
- ASSERT(context()->IsAccumulatorValue() || context()->IsStackValue());
+ DCHECK(context()->IsAccumulatorValue() || context()->IsStackValue());
Label materialize_true, materialize_false, done;
VisitForControl(expr->expression(),
&materialize_false,
void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
- ASSERT(expr->expression()->IsValidReferenceExpression());
+ DCHECK(expr->expression()->IsValidReferenceExpression());
Comment cmnt(masm_, "[ CountOperation");
SetSourcePosition(expr->position());
// Evaluate expression and get value.
if (assign_type == VARIABLE) {
- ASSERT(expr->expression()->AsVariableProxy()->var() != NULL);
+ DCHECK(expr->expression()->AsVariableProxy()->var() != NULL);
AccumulatorValueContext context(this);
EmitVariableLoad(expr->expression()->AsVariableProxy());
} else {
__ push(Immediate(Smi::FromInt(0)));
}
if (assign_type == NAMED_PROPERTY) {
- // Put the object both on the stack and in edx.
- VisitForAccumulatorValue(prop->obj());
- __ push(eax);
- __ mov(edx, eax);
+ // Put the object both on the stack and in the register.
+ VisitForStackValue(prop->obj());
+ __ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
EmitNamedPropertyLoad(prop);
} else {
VisitForStackValue(prop->obj());
VisitForStackValue(prop->key());
- __ mov(edx, Operand(esp, kPointerSize)); // Object.
- __ mov(ecx, Operand(esp, 0)); // Key.
+ __ mov(LoadDescriptor::ReceiverRegister(),
+ Operand(esp, kPointerSize)); // Object.
+ __ mov(LoadDescriptor::NameRegister(), Operand(esp, 0)); // Key.
EmitKeyedPropertyLoad(prop);
}
}
__ bind(&stub_call);
__ mov(edx, eax);
__ mov(eax, Immediate(Smi::FromInt(1)));
- BinaryOpICStub stub(isolate(), expr->binary_op(), NO_OVERWRITE);
- CallIC(stub.GetCode(), expr->CountBinOpFeedbackId());
+ Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), expr->binary_op(),
+ NO_OVERWRITE).code();
+ CallIC(code, expr->CountBinOpFeedbackId());
patch_site.EmitPatchInfo();
__ bind(&done);
}
break;
case NAMED_PROPERTY: {
- __ mov(ecx, prop->key()->AsLiteral()->value());
- __ pop(edx);
+ __ mov(StoreDescriptor::NameRegister(),
+ prop->key()->AsLiteral()->value());
+ __ pop(StoreDescriptor::ReceiverRegister());
CallStoreIC(expr->CountStoreFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
break;
}
case KEYED_PROPERTY: {
- __ pop(ecx);
- __ pop(edx);
- Handle<Code> ic = strict_mode() == SLOPPY
- ? isolate()->builtins()->KeyedStoreIC_Initialize()
- : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
+ __ pop(StoreDescriptor::NameRegister());
+ __ pop(StoreDescriptor::ReceiverRegister());
+ Handle<Code> ic =
+ CodeFactory::KeyedStoreIC(isolate(), strict_mode()).code();
CallIC(ic, expr->CountStoreFeedbackId());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
VariableProxy* proxy = expr->AsVariableProxy();
- ASSERT(!context()->IsEffect());
- ASSERT(!context()->IsTest());
+ DCHECK(!context()->IsEffect());
+ DCHECK(!context()->IsTest());
if (proxy != NULL && proxy->var()->IsUnallocated()) {
Comment cmnt(masm_, "[ Global variable");
- __ mov(edx, GlobalObjectOperand());
- __ mov(ecx, Immediate(proxy->name()));
+ __ mov(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
+ __ mov(LoadDescriptor::NameRegister(), Immediate(proxy->name()));
+ if (FLAG_vector_ics) {
+ __ mov(VectorLoadICDescriptor::SlotRegister(),
+ Immediate(Smi::FromInt(proxy->VariableFeedbackSlot())));
+ }
// Use a regular load, not a contextual load, to avoid a reference
// error.
CallLoadIC(NOT_CONTEXTUAL);
// Generate code for loading from variables potentially shadowed
// by eval-introduced variables.
- EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
+ EmitDynamicLookupFastCase(proxy, INSIDE_TYPEOF, &slow, &done);
__ bind(&slow);
__ push(esi);
__ push(Immediate(proxy->name()));
- __ CallRuntime(Runtime::kHiddenLoadContextSlotNoReferenceError, 2);
+ __ CallRuntime(Runtime::kLoadLookupSlotNoReferenceError, 2);
PrepareForBailout(expr, TOS_REG);
__ bind(&done);
__ j(equal, if_true);
__ cmp(eax, isolate()->factory()->false_value());
Split(equal, if_true, if_false, fall_through);
- } else if (FLAG_harmony_typeof &&
- String::Equals(check, factory->null_string())) {
- __ cmp(eax, isolate()->factory()->null_value());
- Split(equal, if_true, if_false, fall_through);
} else if (String::Equals(check, factory->undefined_string())) {
__ cmp(eax, isolate()->factory()->undefined_value());
__ j(equal, if_true);
Split(equal, if_true, if_false, fall_through);
} else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(eax, if_false);
- if (!FLAG_harmony_typeof) {
- __ cmp(eax, isolate()->factory()->null_value());
- __ j(equal, if_true);
- }
+ __ cmp(eax, isolate()->factory()->null_value());
+ __ j(equal, if_true);
__ CmpObjectType(eax, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, edx);
__ j(below, if_false);
__ CmpInstanceType(edx, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
// Record position and call the compare IC.
SetSourcePosition(expr->position());
- Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
+ Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
patch_site.EmitPatchInfo();
void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
- ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
+ DCHECK_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset);
__ mov(Operand(ebp, frame_offset), value);
}
// Fetch it from the context.
__ push(ContextOperand(esi, Context::CLOSURE_INDEX));
} else {
- ASSERT(declaration_scope->is_function_scope());
+ DCHECK(declaration_scope->is_function_scope());
__ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
}
}
void FullCodeGenerator::EnterFinallyBlock() {
// Cook return address on top of stack (smi encoded Code* delta)
- ASSERT(!result_register().is(edx));
+ DCHECK(!result_register().is(edx));
__ pop(edx);
__ sub(edx, Immediate(masm_->CodeObject()));
STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 1);
void FullCodeGenerator::ExitFinallyBlock() {
- ASSERT(!result_register().is(edx));
+ DCHECK(!result_register().is(edx));
// Restore pending message from stack.
__ pop(edx);
ExternalReference pending_message_script =
Address pc) {
Address call_target_address = pc - kIntSize;
Address jns_instr_address = call_target_address - 3;
- ASSERT_EQ(kCallInstruction, *(call_target_address - 1));
+ DCHECK_EQ(kCallInstruction, *(call_target_address - 1));
if (*jns_instr_address == kJnsInstruction) {
- ASSERT_EQ(kJnsOffset, *(call_target_address - 2));
- ASSERT_EQ(isolate->builtins()->InterruptCheck()->entry(),
+ DCHECK_EQ(kJnsOffset, *(call_target_address - 2));
+ DCHECK_EQ(isolate->builtins()->InterruptCheck()->entry(),
Assembler::target_address_at(call_target_address,
unoptimized_code));
return INTERRUPT;
}
- ASSERT_EQ(kNopByteOne, *jns_instr_address);
- ASSERT_EQ(kNopByteTwo, *(call_target_address - 2));
+ DCHECK_EQ(kNopByteOne, *jns_instr_address);
+ DCHECK_EQ(kNopByteTwo, *(call_target_address - 2));
if (Assembler::target_address_at(call_target_address, unoptimized_code) ==
isolate->builtins()->OnStackReplacement()->entry()) {
return ON_STACK_REPLACEMENT;
}
- ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
+ DCHECK_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
Assembler::target_address_at(call_target_address,
unoptimized_code));
return OSR_AFTER_STACK_CHECK;