16 #define __ ACCESS_MASM(masm)
19 MacroAssembler* masm, Label* miss_label, Register receiver,
20 Handle<Name>
name, Register scratch0, Register scratch1) {
22 DCHECK(!receiver.is(scratch0));
23 Counters* counters = masm->isolate()->counters();
24 __ IncrementCounter(counters->negative_lookups(), 1);
25 __ IncrementCounter(counters->negative_lookups_miss(), 1);
29 const int kInterceptorOrAccessCheckNeededMask =
34 Immediate(kInterceptorOrAccessCheckNeededMask));
42 Register properties = scratch0;
47 Heap::kHashTableMapRootIndex);
52 properties,
name, scratch1);
54 __ DecrementCounter(counters->negative_lookups_miss(), 1);
59 MacroAssembler* masm,
int index, Register prototype, Label* miss) {
60 Isolate* isolate = masm->isolate();
62 Handle<JSFunction>
function(
63 JSFunction::cast(isolate->native_context()->get(index)));
66 Register scratch = prototype;
68 __ movp(scratch, Operand(
rsi, offset));
74 __ Move(prototype, Handle<Map>(function->initial_map()));
81 MacroAssembler* masm, Register receiver, Register result, Register scratch,
83 __ TryGetFunctionPrototype(receiver, result, miss_label);
84 if (!result.is(
rax))
__ movp(
rax, result);
89 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
90 Register holder, Register
name,
91 Handle<JSObject> holder_obj) {
98 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
99 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
107 static void CompileCallLoadPropertyWithInterceptor(
108 MacroAssembler* masm, Register receiver, Register holder, Register
name,
110 PushInterceptorArguments(masm, receiver, holder,
name, holder_obj);
111 __ CallExternalReference(ExternalReference(IC_Utility(
id), masm->isolate()),
118 MacroAssembler* masm,
const CallOptimization& optimization,
119 Handle<Map> receiver_map, Register receiver, Register scratch_in,
120 bool is_store,
int argc, Register* values) {
121 DCHECK(optimization.is_simple_api_call());
123 __ PopReturnAddressTo(scratch_in);
127 for (
int i = 0;
i < argc;
i++) {
128 Register arg = values[argc - 1 -
i];
129 DCHECK(!receiver.is(arg));
130 DCHECK(!scratch_in.is(arg));
133 __ PushReturnAddressFrom(scratch_in);
137 Register callee =
rax;
138 Register call_data =
rbx;
140 Register api_function_address =
rdx;
141 Register scratch =
rdi;
144 CallOptimization::HolderLookup holder_lookup;
145 Handle<JSObject> api_holder =
146 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
147 switch (holder_lookup) {
148 case CallOptimization::kHolderIsReceiver:
151 case CallOptimization::kHolderFound:
154 case CallOptimization::kHolderNotFound:
159 Isolate* isolate = masm->isolate();
160 Handle<JSFunction>
function = optimization.constant_function();
161 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
162 Handle<Object> call_data_obj(api_call_info->data(), isolate);
165 __ Move(callee,
function);
167 bool call_data_undefined =
false;
169 if (isolate->heap()->InNewSpace(*call_data_obj)) {
170 __ Move(scratch, api_call_info);
172 }
else if (call_data_obj->IsUndefined()) {
173 call_data_undefined =
true;
174 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
176 __ Move(call_data, call_data_obj);
180 Address function_address = v8::ToCData<Address>(api_call_info->callback());
181 __ Move(api_function_address, function_address,
185 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
186 __ TailCallStub(&stub);
191 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name>
name,
192 Register scratch, Label* miss) {
194 DCHECK(cell->value()->IsTheHole());
195 __ Move(scratch, cell);
197 masm->isolate()->factory()->the_hole_value());
203 MacroAssembler* masm, Handle<HeapType> type, Register receiver,
204 Handle<JSFunction> setter) {
214 if (!setter.is_null()) {
223 ParameterCount actual(1);
224 ParameterCount expected(setter);
230 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
244 MacroAssembler* masm, Handle<HeapType> type, Register receiver,
245 Handle<JSFunction> getter) {
254 if (!getter.is_null()) {
262 ParameterCount actual(0);
263 ParameterCount expected(getter);
269 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
279 static void StoreIC_PushArgs(MacroAssembler* masm) {
286 __ PopReturnAddressTo(
rbx);
290 __ PushReturnAddressFrom(
rbx);
296 StoreIC_PushArgs(masm);
299 ExternalReference ref(IC_Utility(IC::kStoreIC_Slow), masm->isolate());
300 __ TailCallExternalReference(ref, 3, 1);
306 StoreIC_PushArgs(masm);
309 ExternalReference ref(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate());
310 __ TailCallExternalReference(ref, 3, 1);
315 #define __ ACCESS_MASM((masm()))
320 if (!label->is_unused()) {
322 __ Move(this->
name(), name);
330 Handle<Map> transition, Handle<Name>
name, Register receiver_reg,
331 Register storage_reg, Register value_reg, Register scratch1,
332 Register scratch2, Register unused, Label* miss_label, Label* slow) {
333 int descriptor = transition->LastAdded();
334 DescriptorArray* descriptors = transition->instance_descriptors();
335 PropertyDetails details = descriptors->GetDetails(descriptor);
336 Representation representation = details.representation();
337 DCHECK(!representation.IsNone());
340 Handle<Object> constant(descriptors->GetValue(descriptor), isolate());
341 __ Cmp(value_reg, constant);
343 }
else if (representation.IsSmi()) {
344 __ JumpIfNotSmi(value_reg, miss_label);
345 }
else if (representation.IsHeapObject()) {
346 __ JumpIfSmi(value_reg, miss_label);
347 HeapType* field_type = descriptors->GetFieldType(descriptor);
348 HeapType::Iterator<Map> it = field_type->Classes();
352 __ CompareMap(value_reg, it.Current());
358 __ j(
equal, &do_store, Label::kNear);
362 }
else if (representation.IsDouble()) {
363 Label do_store, heap_number;
364 __ AllocateHeapNumber(storage_reg, scratch1, slow,
MUTABLE);
366 __ JumpIfNotSmi(value_reg, &heap_number);
367 __ SmiToInteger32(scratch1, value_reg);
368 __ Cvtlsi2sd(
xmm0, scratch1);
371 __ bind(&heap_number);
372 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label,
381 DCHECK(!transition->is_access_check_needed());
384 if (details.type() ==
FIELD &&
385 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
388 __ PopReturnAddressTo(scratch1);
392 __ PushReturnAddressFrom(scratch1);
393 __ TailCallExternalReference(
394 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
401 __ Move(scratch1, transition);
414 int index = transition->instance_descriptors()->GetFieldIndex(
415 transition->LastAdded());
420 index -= transition->inobject_properties();
427 int offset = transition->instance_size() + (index *
kPointerSize);
428 if (representation.IsDouble()) {
434 if (!representation.IsSmi()) {
436 if (!representation.IsDouble()) {
437 __ movp(storage_reg, value_reg);
439 __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
447 if (representation.IsDouble()) {
453 if (!representation.IsSmi()) {
455 if (!representation.IsDouble()) {
456 __ movp(storage_reg, value_reg);
458 __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
472 DCHECK(lookup->representation().IsHeapObject());
473 __ JumpIfSmi(value_reg, miss_label);
474 HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
477 __ CompareMap(value_reg, it.Current());
483 __ j(
equal, &do_store, Label::kNear);
487 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
488 lookup->representation());
489 GenerateTailCall(masm(), stub.GetCode());
494 Register object_reg, Register holder_reg, Register scratch1,
495 Register scratch2, Handle<Name>
name, Label* miss,
500 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
501 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
502 !scratch2.is(scratch1));
507 Register reg = object_reg;
511 if (
type()->IsConstant()) {
515 Handle<Map> current_map = receiver_map;
519 while (!current_map.is_identical_to(holder_map)) {
524 DCHECK(current_map->IsJSGlobalProxyMap() ||
525 !current_map->is_access_check_needed());
527 prototype =
handle(JSObject::cast(current_map->prototype()));
528 if (current_map->is_dictionary_map() &&
529 !current_map->IsJSGlobalObjectMap()) {
530 DCHECK(!current_map->IsJSGlobalProxyMap());
531 if (!
name->IsUniqueName()) {
535 DCHECK(current.is_null() ||
536 current->property_dictionary()->FindEntry(
name) ==
546 bool in_new_space = heap()->InNewSpace(*prototype);
551 bool load_prototype_from_map = in_new_space || depth == 1;
552 if (load_prototype_from_map) {
566 if (current_map->IsJSGlobalProxyMap()) {
567 __ CheckAccessGlobalProxy(reg, scratch2, miss);
568 }
else if (current_map->IsJSGlobalObjectMap()) {
570 name, scratch2, miss);
574 if (load_prototype_from_map) {
577 __ Move(reg, prototype);
583 current_map =
handle(current->map());
587 LOG(isolate(), IntEvent(
"check-maps-depth", depth + 1));
595 DCHECK(current_map->IsJSGlobalProxyMap() ||
596 !current_map->is_access_check_needed());
597 if (current_map->IsJSGlobalProxyMap()) {
598 __ CheckAccessGlobalProxy(reg, scratch1, miss);
607 if (!miss->is_unused()) {
611 TailCallBuiltin(masm(), MissBuiltin(kind()));
618 if (!miss->is_unused()) {
622 TailCallBuiltin(masm(), MissBuiltin(kind()));
629 Register reg, Handle<ExecutableAccessorInfo> callback) {
642 if (heap()->InNewSpace(callback->data())) {
643 DCHECK(!scratch2().is(reg));
644 __ Move(scratch2(), callback);
648 __ Push(Handle<Object>(callback->data(), isolate()));
654 __ PushAddress(ExternalReference::isolate_address(isolate()));
664 Address getter_address = v8::ToCData<Address>(callback->getter());
667 CallApiGetterStub stub(isolate());
668 __ TailCallStub(&stub);
680 LookupIterator* it, Register holder_reg) {
682 DCHECK(!
holder()->GetNamedInterceptor()->getter()->IsUndefined());
687 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
693 bool must_perform_prototype_check =
694 !
holder().is_identical_to(it->GetHolder<JSObject>());
695 bool must_preserve_receiver_reg =
696 !receiver().is(holder_reg) &&
704 if (must_preserve_receiver_reg) {
713 CompileCallLoadPropertyWithInterceptor(
714 masm(), receiver(), holder_reg, this->
name(),
holder(),
715 IC::kLoadPropertyWithInterceptorOnly);
719 Label interceptor_failed;
720 __ CompareRoot(
rax, Heap::kNoInterceptorResultSentinelRootIndex);
721 __ j(
equal, &interceptor_failed);
722 frame_scope.GenerateLeaveFrame();
725 __ bind(&interceptor_failed);
728 if (must_preserve_receiver_reg) {
742 DCHECK(!
holder()->GetNamedInterceptor()->getter()->IsUndefined());
743 __ PopReturnAddressTo(scratch2());
744 PushInterceptorArguments(masm(), receiver(), holder_reg, this->
name(),
746 __ PushReturnAddressFrom(scratch2());
748 ExternalReference ref = ExternalReference(
749 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
750 __ TailCallExternalReference(
756 Handle<JSObject>
object, Handle<Name>
name,
757 Handle<ExecutableAccessorInfo> callback) {
760 __ PopReturnAddressTo(scratch1());
766 __ PushReturnAddressFrom(scratch1());
769 ExternalReference store_callback_property =
770 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
771 __ TailCallExternalReference(store_callback_property, 5, 1);
780 __ PopReturnAddressTo(scratch1());
784 __ PushReturnAddressFrom(scratch1());
787 ExternalReference store_ic_property = ExternalReference(
788 IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
789 __ TailCallExternalReference(store_ic_property, 3, 1);
802 Handle<PropertyCell> cell, Handle<Name>
name,
bool is_configurable) {
808 __ Move(result, cell);
812 if (is_configurable) {
813 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
815 }
else if (FLAG_debug_code) {
816 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
817 __ Check(
not_equal, kDontDeleteCellsCannotContainTheHole);
820 Counters* counters = isolate()->counters();
821 __ IncrementCounter(counters->named_load_global_stub(), 1);
static const Register function_address()
static const int kDataOffset
static const int kValueOffset
static int SlotOffset(int index)
static const int kReturnValueOffset
static void GenerateStoreSlow(MacroAssembler *masm)
static const int kDataOffset
static const int kHeaderSize
static const int kNativeContextOffset
static const int kGlobalProxyOffset
static Handle< T > cast(Handle< S > that)
static Handle< T > null()
static const int kNotFound
static const int kValueOffset
static const int kMapOffset
static Handle< Map > TypeToMap(HeapType *type, Isolate *isolate)
static Handle< PropertyCell > EnsurePropertyCell(Handle< JSGlobalObject > global, Handle< Name > name)
static const int kPropertiesOffset
static const int kBitFieldOffset
static const int kIsAccessCheckNeeded
static const int kHasNamedInterceptor
static const int kPrototypeOffset
static void GenerateNegativeLookup(MacroAssembler *masm, Label *miss, Label *done, Register receiver, Register properties, Handle< Name > name, Register scratch0)
static const int kInterceptorArgsNameIndex
static const int kInterceptorArgsInfoIndex
Handle< Code > CompileLoadGlobal(Handle< PropertyCell > cell, Handle< Name > name, bool is_configurable)
static const int kInterceptorArgsThisIndex
virtual void FrontendFooter(Handle< Name > name, Label *miss)
static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler *masm, int index, Register prototype, Label *miss)
void GenerateLoadInterceptorWithFollowup(LookupIterator *it, Register holder_reg)
virtual Register FrontendHeader(Register object_reg, Handle< Name > name, Label *miss)
static const int kInterceptorArgsHolderIndex
void GenerateLoadConstant(Handle< Object > value)
void GenerateLoadInterceptor(Register holder_reg)
static void GenerateLoadFunctionPrototype(MacroAssembler *masm, Register receiver, Register scratch1, Register scratch2, Label *miss_label)
static const int kInterceptorArgsLength
void GenerateLoadPostInterceptor(LookupIterator *it, Register reg)
static void GenerateLoadViaGetter(MacroAssembler *masm, Handle< HeapType > type, Register receiver, Handle< JSFunction > getter)
void GenerateLoadCallback(Register reg, Handle< ExecutableAccessorInfo > callback)
Handle< Code > CompileStoreInterceptor(Handle< Name > name)
virtual void FrontendFooter(Handle< Name > name, Label *miss)
void GenerateStoreField(LookupIterator *lookup, Register value_reg, Label *miss_label)
Handle< Code > CompileStoreCallback(Handle< JSObject > object, Handle< Name > name, Handle< ExecutableAccessorInfo > callback)
static void GenerateSlow(MacroAssembler *masm)
void GenerateRestoreName(Label *label, Handle< Name > name)
void GenerateStoreTransition(Handle< Map > transition, Handle< Name > name, Register receiver_reg, Register name_reg, Register value_reg, Register scratch1, Register scratch2, Register scratch3, Label *miss_label, Label *slow)
static void GenerateStoreViaSetter(MacroAssembler *masm, Handle< HeapType > type, Register receiver, Handle< JSFunction > setter)
static const int kArgsLength
static const int kHolderIndex
static const int kDataIndex
static const int kIsolateIndex
static const int kThisIndex
static const int kReturnValueDefaultValueIndex
Handle< JSObject > holder() const
Register CheckPrototypes(Register object_reg, Register holder_reg, Register scratch1, Register scratch2, Handle< Name > name, Label *miss, PrototypeCheckType check=CHECK_ALL_MAPS)
Handle< Code > GetCode(Code::Kind kind, Code::StubType type, Handle< Name > name)
Handle< HeapType > type() const
static void GenerateDictionaryNegativeLookup(MacroAssembler *masm, Label *miss_label, Register receiver, Handle< Name > name, Register r0, Register r1)
static void GenerateFastApiCall(MacroAssembler *masm, const CallOptimization &optimization, Handle< Map > receiver_map, Register receiver, Register scratch, bool is_store, int argc, Register *values)
Register Frontend(Register object_reg, Handle< Name > name)
static void GenerateCheckPropertyCell(MacroAssembler *masm, Handle< JSGlobalObject > global, Handle< Name > name, Register scratch, Label *miss)
static const int kContextOffset
static const Register ReceiverRegister()
static const Register NameRegister()
static const Register ValueRegister()
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
#define LOG(isolate, Call)
#define DCHECK(condition)
static int Push(SpecialRPOStackFrame *stack, int depth, BasicBlock *child, int unvisited)
const Register kScratchRegister
Operand FieldOperand(Register object, int offset)
TypeImpl< HeapTypeConfig > HeapType
Handle< T > handle(T *t, Isolate *isolate)
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
Debugger support for the V8 JavaScript engine.
bool is(Register reg) const