Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/ic/handler-compiler.h"
6 :
7 : #include "src/assembler-inl.h"
8 : #include "src/field-type.h"
9 : #include "src/ic/call-optimization.h"
10 : #include "src/ic/handler-configuration-inl.h"
11 : #include "src/ic/ic-inl.h"
12 : #include "src/ic/ic.h"
13 : #include "src/isolate-inl.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 245699 : Handle<Code> PropertyHandlerCompiler::GetCode(Handle<Name> name) {
19 : // Create code object in the heap.
20 : CodeDesc desc;
21 491398 : masm()->GetCode(isolate(), &desc);
22 : Handle<Code> code =
23 245699 : factory()->NewCode(desc, Code::STUB, masm()->CodeObject());
24 : DCHECK(code->is_stub());
25 : code->set_stub_key(CodeStub::NoCacheKey());
26 : #ifdef ENABLE_DISASSEMBLER
27 : if (FLAG_print_code_stubs) {
28 : char* raw_name = !name.is_null() && name->IsString()
29 : ? String::cast(*name)->ToCString().get()
30 : : nullptr;
31 : CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
32 : OFStream os(trace_scope.file());
33 : code->Disassemble(raw_name, os);
34 : }
35 : #endif
36 :
37 245699 : PROFILE(isolate(), CodeCreateEvent(CodeEventListener::HANDLER_TAG,
38 : AbstractCode::cast(*code), *name));
39 :
40 : #ifdef DEBUG
41 : code->VerifyEmbeddedObjects();
42 : #endif
43 245699 : return code;
44 : }
45 :
46 :
47 : #define __ ACCESS_MASM(masm())
48 :
49 3512 : Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
50 : Handle<Name> name,
51 3512 : Label* miss) {
52 3512 : if (map()->IsPrimitiveMap() || map()->IsJSGlobalProxyMap()) {
53 : // If the receiver is a global proxy and if we get to this point then
54 : // the compile-time (current) native context has access to global proxy's
55 : // native context. Since access rights revocation is not supported at all,
56 : // we can generate a check that an execution-time native context is either
57 : // the same as compile-time native context or has the same access token.
58 10 : Handle<Context> native_context = isolate()->native_context();
59 : Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
60 :
61 : bool compare_native_contexts_only = map()->IsPrimitiveMap();
62 : GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss,
63 10 : compare_native_contexts_only);
64 : }
65 :
66 : // Check that the maps starting from the prototype haven't changed.
67 : return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
68 3512 : miss);
69 : }
70 :
71 :
72 : // Frontend for store uses the name register. It has to be restored before a
73 : // miss.
74 242187 : Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
75 : Handle<Name> name,
76 : Label* miss) {
77 242187 : if (map()->IsJSGlobalProxyMap()) {
78 242323 : Handle<Context> native_context = isolate()->native_context();
79 : Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
80 68 : GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss, false);
81 : }
82 :
83 : return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
84 242187 : miss);
85 : }
86 :
87 : // The ICs that don't pass slot and vector through the stack have to
88 : // save/restore them in the dispatcher.
89 491398 : bool PropertyHandlerCompiler::ShouldPushPopSlotAndVector() {
90 491398 : switch (type()) {
91 : case LOAD:
92 : return true;
93 : case STORE:
94 : return !StoreWithVectorDescriptor::kPassLastArgsOnStack;
95 : }
96 0 : UNREACHABLE();
97 : return false;
98 : }
99 :
100 245699 : Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
101 : Label miss;
102 245699 : if (ShouldPushPopSlotAndVector()) PushVectorAndSlot();
103 491398 : Register reg = FrontendHeader(receiver(), name, &miss);
104 245699 : FrontendFooter(name, &miss);
105 : // The footer consumes the vector and slot from the stack if miss occurs.
106 245699 : if (ShouldPushPopSlotAndVector()) DiscardVectorAndSlot();
107 245699 : return reg;
108 : }
109 :
110 3512 : Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
111 : Handle<Name> name, const CallOptimization& call_optimization,
112 : int accessor_index, Handle<Code> slow_stub) {
113 : DCHECK(call_optimization.is_simple_api_call());
114 3512 : if (V8_UNLIKELY(FLAG_runtime_stats)) {
115 3512 : GenerateTailCall(masm(), slow_stub);
116 : }
117 3512 : Register holder = Frontend(name);
118 : GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
119 3512 : scratch2(), false, no_reg, holder, accessor_index);
120 3512 : return GetCode(name);
121 : }
122 :
123 141317 : Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
124 : Handle<JSObject> object, Handle<Name> name, int accessor_index,
125 : int expected_arguments) {
126 141317 : Register holder = Frontend(name);
127 : GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index,
128 282634 : expected_arguments, scratch2());
129 :
130 141317 : return GetCode(name);
131 : }
132 :
133 274 : Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
134 : Handle<JSObject> object, Handle<Name> name,
135 : const CallOptimization& call_optimization, int accessor_index,
136 : Handle<Code> slow_stub) {
137 274 : if (V8_UNLIKELY(FLAG_runtime_stats)) {
138 274 : GenerateTailCall(masm(), slow_stub);
139 : }
140 274 : Register holder = Frontend(name);
141 : if (Descriptor::kPassLastArgsOnStack) {
142 : __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
143 : }
144 : GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
145 : receiver(), scratch2(), true, value(), holder,
146 548 : accessor_index);
147 274 : return GetCode(name);
148 : }
149 :
150 :
151 : #undef __
152 :
153 : } // namespace internal
154 : } // namespace v8
|