16 #define __ ACCESS_MASM(masm)
20 MacroAssembler* masm, Handle<HeapType> type, Register receiver,
21 Handle<JSFunction> getter) {
30 if (!getter.is_null()) {
38 ParameterCount actual(0);
39 ParameterCount expected(getter);
45 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
56 MacroAssembler* masm, Handle<HeapType> type, Register receiver,
57 Handle<JSFunction> setter) {
67 if (!setter.is_null()) {
75 ParameterCount actual(1);
76 ParameterCount expected(setter);
82 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
96 MacroAssembler* masm, Label* miss_label, Register receiver,
97 Handle<Name>
name, Register scratch0, Register scratch1) {
99 DCHECK(!receiver.is(scratch0));
100 Counters* counters = masm->isolate()->counters();
101 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
102 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
106 const int kInterceptorOrAccessCheckNeededMask =
110 Register
map = scratch1;
113 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
114 __ b(
ne, miss_label);
119 __ b(
lt, miss_label);
122 Register properties = scratch0;
126 Register tmp = properties;
127 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
129 __ b(
ne, miss_label);
136 masm, miss_label, &done, receiver, properties,
name, scratch1);
138 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
143 MacroAssembler* masm,
int index, Register prototype, Label* miss) {
144 Isolate* isolate = masm->isolate();
146 Handle<JSFunction>
function(
147 JSFunction::cast(isolate->native_context()->get(index)));
150 Register scratch = prototype;
155 __ Move(
ip,
function);
160 __ Move(prototype, Handle<Map>(function->initial_map()));
167 MacroAssembler* masm, Register receiver, Register scratch1,
168 Register scratch2, Label* miss_label) {
169 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
170 __ mov(
r0, scratch1);
179 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name>
name,
180 Register scratch, Label* miss) {
182 DCHECK(cell->value()->IsTheHole());
183 __ mov(scratch, Operand(cell));
185 __ LoadRoot(
ip, Heap::kTheHoleValueRootIndex);
191 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
192 Register holder, Register
name,
193 Handle<JSObject> holder_obj) {
200 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
201 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
202 Register scratch =
name;
203 __ mov(scratch, Operand(interceptor));
210 static void CompileCallLoadPropertyWithInterceptor(
211 MacroAssembler* masm, Register receiver, Register holder, Register
name,
213 PushInterceptorArguments(masm, receiver, holder,
name, holder_obj);
214 __ CallExternalReference(ExternalReference(IC_Utility(
id), masm->isolate()),
221 MacroAssembler* masm,
const CallOptimization& optimization,
222 Handle<Map> receiver_map, Register receiver, Register scratch_in,
223 bool is_store,
int argc, Register* values) {
224 DCHECK(!receiver.is(scratch_in));
227 for (
int i = 0;
i < argc;
i++) {
228 Register arg = values[argc - 1 -
i];
229 DCHECK(!receiver.is(arg));
230 DCHECK(!scratch_in.is(arg));
233 DCHECK(optimization.is_simple_api_call());
236 Register callee =
r0;
237 Register call_data =
r4;
239 Register api_function_address =
r1;
242 CallOptimization::HolderLookup holder_lookup;
243 Handle<JSObject> api_holder =
244 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
245 switch (holder_lookup) {
246 case CallOptimization::kHolderIsReceiver:
249 case CallOptimization::kHolderFound:
252 case CallOptimization::kHolderNotFound:
257 Isolate* isolate = masm->isolate();
258 Handle<JSFunction>
function = optimization.constant_function();
259 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
260 Handle<Object> call_data_obj(api_call_info->data(), isolate);
263 __ Move(callee,
function);
265 bool call_data_undefined =
false;
267 if (isolate->heap()->InNewSpace(*call_data_obj)) {
268 __ Move(call_data, api_call_info);
270 }
else if (call_data_obj->IsUndefined()) {
271 call_data_undefined =
true;
272 __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
274 __ Move(call_data, call_data_obj);
278 Address function_address = v8::ToCData<Address>(api_call_info->callback());
279 ApiFunction fun(function_address);
281 ExternalReference ref = ExternalReference(&fun,
type, masm->isolate());
282 __ mov(api_function_address, Operand(ref));
285 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
286 __ TailCallStub(&stub);
297 ExternalReference ref =
298 ExternalReference(IC_Utility(IC::kStoreIC_Slow), masm->isolate());
299 __ TailCallExternalReference(ref, 3, 1);
310 ExternalReference ref =
311 ExternalReference(IC_Utility(IC::kKeyedStoreIC_Slow), masm->isolate());
312 __ TailCallExternalReference(ref, 3, 1);
317 #define __ ACCESS_MASM(masm())
322 if (!label->is_unused()) {
334 Handle<Map> transition, Handle<Name>
name, Register receiver_reg,
335 Register storage_reg, Register value_reg, Register scratch1,
336 Register scratch2, Register scratch3, Label* miss_label, Label* slow) {
340 int descriptor = transition->LastAdded();
341 DescriptorArray* descriptors = transition->instance_descriptors();
342 PropertyDetails details = descriptors->GetDetails(descriptor);
343 Representation representation = details.representation();
344 DCHECK(!representation.IsNone());
347 Handle<Object> constant(descriptors->GetValue(descriptor), isolate());
348 __ Move(scratch1, constant);
349 __ cmp(value_reg, scratch1);
350 __ b(
ne, miss_label);
351 }
else if (representation.IsSmi()) {
352 __ JumpIfNotSmi(value_reg, miss_label);
353 }
else if (representation.IsHeapObject()) {
354 __ JumpIfSmi(value_reg, miss_label);
355 HeapType* field_type = descriptors->GetFieldType(descriptor);
356 HeapType::Iterator<Map> it = field_type->Classes();
361 __ CompareMap(scratch1, it.Current(), &do_store);
364 __ b(
ne, miss_label);
371 }
else if (representation.IsDouble()) {
372 Label do_store, heap_number;
373 __ LoadRoot(scratch3, Heap::kMutableHeapNumberMapRootIndex);
374 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow,
377 __ JumpIfNotSmi(value_reg, &heap_number);
378 __ SmiUntag(scratch1, value_reg);
379 __ vmov(
s0, scratch1);
383 __ bind(&heap_number);
384 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, miss_label,
393 DCHECK(!transition->is_access_check_needed());
396 if (details.type() ==
FIELD &&
397 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
400 __ push(receiver_reg);
401 __ mov(
r2, Operand(transition));
403 __ TailCallExternalReference(
404 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
411 __ mov(scratch1, Operand(transition));
425 int index = transition->instance_descriptors()->GetFieldIndex(
426 transition->LastAdded());
431 index -= transition->inobject_properties();
438 int offset = transition->instance_size() + (index *
kPointerSize);
439 if (representation.IsDouble()) {
445 if (!representation.IsSmi()) {
447 if (!representation.IsDouble()) {
448 __ mov(storage_reg, value_reg);
450 __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
460 if (representation.IsDouble()) {
466 if (!representation.IsSmi()) {
468 if (!representation.IsDouble()) {
469 __ mov(storage_reg, value_reg);
471 __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
487 DCHECK(lookup->representation().IsHeapObject());
488 __ JumpIfSmi(value_reg, miss_label);
489 HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes();
493 __ CompareMap(scratch1(), it.Current(), &do_store);
496 __ b(
ne, miss_label);
503 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
504 lookup->representation());
505 GenerateTailCall(masm(), stub.GetCode());
510 Register object_reg, Register holder_reg, Register scratch1,
511 Register scratch2, Handle<Name>
name, Label* miss,
516 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
517 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
518 !scratch2.is(scratch1));
521 Register reg = object_reg;
525 if (
type()->IsConstant()) {
529 Handle<Map> current_map = receiver_map;
533 while (!current_map.is_identical_to(holder_map)) {
538 DCHECK(current_map->IsJSGlobalProxyMap() ||
539 !current_map->is_access_check_needed());
541 prototype =
handle(JSObject::cast(current_map->prototype()));
542 if (current_map->is_dictionary_map() &&
543 !current_map->IsJSGlobalObjectMap()) {
544 DCHECK(!current_map->IsJSGlobalProxyMap());
545 if (!
name->IsUniqueName()) {
549 DCHECK(current.is_null() ||
550 current->property_dictionary()->FindEntry(
name) ==
560 Register map_reg = scratch1;
574 if (current_map->IsJSGlobalProxyMap()) {
575 __ CheckAccessGlobalProxy(reg, scratch2, miss);
576 }
else if (current_map->IsJSGlobalObjectMap()) {
578 name, scratch2, miss);
587 bool load_prototype_from_map =
588 heap()->InNewSpace(*prototype) || depth == 1;
589 if (load_prototype_from_map) {
592 __ mov(reg, Operand(prototype));
598 current_map =
handle(current->map());
602 LOG(isolate(), IntEvent(
"check-maps-depth", depth + 1));
610 DCHECK(current_map->IsJSGlobalProxyMap() ||
611 !current_map->is_access_check_needed());
612 if (current_map->IsJSGlobalProxyMap()) {
613 __ CheckAccessGlobalProxy(reg, scratch1, miss);
622 if (!miss->is_unused()) {
626 TailCallBuiltin(masm(), MissBuiltin(kind()));
633 if (!miss->is_unused()) {
637 TailCallBuiltin(masm(), MissBuiltin(kind()));
651 Register reg, Handle<ExecutableAccessorInfo> callback) {
661 DCHECK(!scratch2().is(reg));
662 DCHECK(!scratch3().is(reg));
665 if (heap()->InNewSpace(callback->data())) {
666 __ Move(scratch3(), callback);
670 __ Move(scratch3(), Handle<Object>(callback->data(), isolate()));
673 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
676 __ mov(
scratch4(), Operand(ExternalReference::isolate_address(isolate())));
678 __ mov(scratch2(),
sp);
684 Address getter_address = v8::ToCData<Address>(callback->getter());
685 ApiFunction fun(getter_address);
687 ExternalReference ref = ExternalReference(&fun,
type, isolate());
688 __ mov(getter_address_reg, Operand(ref));
690 CallApiGetterStub stub(isolate());
691 __ TailCallStub(&stub);
696 LookupIterator* it, Register holder_reg) {
698 DCHECK(!
holder()->GetNamedInterceptor()->getter()->IsUndefined());
703 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1()));
709 bool must_perform_prototype_check =
710 !
holder().is_identical_to(it->GetHolder<JSObject>());
711 bool must_preserve_receiver_reg =
712 !receiver().is(holder_reg) &&
719 if (must_preserve_receiver_reg) {
720 __ Push(receiver(), holder_reg, this->
name());
727 CompileCallLoadPropertyWithInterceptor(
728 masm(), receiver(), holder_reg, this->
name(),
holder(),
729 IC::kLoadPropertyWithInterceptorOnly);
733 Label interceptor_failed;
734 __ LoadRoot(scratch1(), Heap::kNoInterceptorResultSentinelRootIndex);
735 __ cmp(
r0, scratch1());
736 __ b(
eq, &interceptor_failed);
737 frame_scope.GenerateLeaveFrame();
740 __ bind(&interceptor_failed);
743 if (must_preserve_receiver_reg) {
756 DCHECK(!
holder()->GetNamedInterceptor()->getter()->IsUndefined());
757 PushInterceptorArguments(masm(), receiver(), holder_reg, this->
name(),
760 ExternalReference ref = ExternalReference(
761 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate());
762 __ TailCallExternalReference(
768 Handle<JSObject>
object, Handle<Name>
name,
769 Handle<ExecutableAccessorInfo> callback) {
774 __ mov(
ip, Operand(callback));
780 ExternalReference store_callback_property =
781 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
782 __ TailCallExternalReference(store_callback_property, 5, 1);
794 ExternalReference store_ic_property = ExternalReference(
795 IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
796 __ TailCallExternalReference(store_ic_property, 3, 1);
809 Handle<PropertyCell> cell, Handle<Name>
name,
bool is_configurable) {
815 __ mov(result, Operand(cell));
819 if (is_configurable) {
820 __ LoadRoot(
ip, Heap::kTheHoleValueRootIndex);
825 Counters* counters = isolate()->counters();
826 __ IncrementCounter(counters->named_load_global_stub(), 1,
r1,
r3);
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 kInstanceTypeOffset
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)
TypeImpl< ZoneTypeConfig > Type
const LowDwVfpRegister d0
TypeImpl< HeapTypeConfig > HeapType
Handle< T > handle(T *t, Isolate *isolate)
MemOperand FieldMemOperand(Register object, int offset)
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
Debugger support for the V8 JavaScript engine.