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 41492 : Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name,
19 : Handle<Map> stub_holder,
20 : Code::Kind kind) {
21 : Code::Flags flags = Code::ComputeHandlerFlags(kind);
22 41492 : Code* code = stub_holder->LookupInCodeCache(*name, flags);
23 41492 : if (code == nullptr) return Handle<Code>();
24 : return handle(code);
25 : }
26 :
27 38698 : Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
28 : Handle<Name> name) {
29 : Code::Flags flags = Code::ComputeHandlerFlags(kind);
30 :
31 : // Create code object in the heap.
32 : CodeDesc desc;
33 77396 : masm()->GetCode(&desc);
34 38698 : Handle<Code> code = factory()->NewCode(desc, flags, masm()->CodeObject());
35 38698 : if (code->IsCodeStubOrIC()) code->set_stub_key(CodeStub::NoCacheKey());
36 : #ifdef ENABLE_DISASSEMBLER
37 : if (FLAG_print_code_stubs) {
38 : char* raw_name = !name.is_null() && name->IsString()
39 : ? String::cast(*name)->ToCString().get()
40 : : nullptr;
41 : CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
42 : OFStream os(trace_scope.file());
43 : code->Disassemble(raw_name, os);
44 : }
45 : #endif
46 :
47 38698 : PROFILE(isolate(), CodeCreateEvent(CodeEventListener::HANDLER_TAG,
48 : AbstractCode::cast(*code), *name));
49 :
50 : #ifdef DEBUG
51 : code->VerifyEmbeddedObjects();
52 : #endif
53 38698 : return code;
54 : }
55 :
56 :
57 : #define __ ACCESS_MASM(masm())
58 :
59 277 : Register NamedLoadHandlerCompiler::FrontendHeader(Register object_reg,
60 : Handle<Name> name,
61 277 : Label* miss) {
62 554 : if (map()->IsPrimitiveMap() || map()->IsJSGlobalProxyMap()) {
63 : // If the receiver is a global proxy and if we get to this point then
64 : // the compile-time (current) native context has access to global proxy's
65 : // native context. Since access rights revocation is not supported at all,
66 : // we can generate a check that an execution-time native context is either
67 : // the same as compile-time native context or has the same access token.
68 12 : Handle<Context> native_context = isolate()->native_context();
69 : Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
70 :
71 : bool compare_native_contexts_only = map()->IsPrimitiveMap();
72 : GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss,
73 12 : compare_native_contexts_only);
74 : }
75 :
76 : // Check that the maps starting from the prototype haven't changed.
77 : return CheckPrototypes(object_reg, scratch1(), scratch2(), scratch3(), name,
78 277 : miss);
79 : }
80 :
81 :
82 : // Frontend for store uses the name register. It has to be restored before a
83 : // miss.
84 38421 : Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg,
85 : Handle<Name> name,
86 : Label* miss) {
87 38421 : if (map()->IsJSGlobalProxyMap()) {
88 38573 : Handle<Context> native_context = isolate()->native_context();
89 : Handle<WeakCell> weak_cell(native_context->self_weak_cell(), isolate());
90 76 : GenerateAccessCheck(weak_cell, scratch1(), scratch2(), miss, false);
91 : }
92 :
93 : return CheckPrototypes(object_reg, this->name(), scratch1(), scratch2(), name,
94 38421 : miss);
95 : }
96 :
97 :
98 38698 : Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
99 : Label miss;
100 116094 : if (IC::ShouldPushPopSlotAndVector(kind())) {
101 38698 : PushVectorAndSlot();
102 : }
103 77396 : Register reg = FrontendHeader(receiver(), name, &miss);
104 38698 : FrontendFooter(name, &miss);
105 : // The footer consumes the vector and slot from the stack if miss occurs.
106 38698 : if (IC::ShouldPushPopSlotAndVector(kind())) {
107 38698 : DiscardVectorAndSlot();
108 : }
109 38698 : return reg;
110 : }
111 :
112 277 : Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
113 : Handle<Name> name, const CallOptimization& call_optimization,
114 : int accessor_index, Handle<Code> slow_stub) {
115 : DCHECK(call_optimization.is_simple_api_call());
116 277 : if (V8_UNLIKELY(FLAG_runtime_stats)) {
117 554 : GenerateTailCall(masm(), slow_stub);
118 : }
119 277 : Register holder = Frontend(name);
120 : GenerateApiAccessorCall(masm(), call_optimization, map(), receiver(),
121 277 : scratch2(), false, no_reg, holder, accessor_index);
122 277 : return GetCode(kind(), name);
123 : }
124 :
125 18064 : Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
126 : Handle<JSObject> object, Handle<Name> name, int accessor_index,
127 : int expected_arguments) {
128 18064 : Register holder = Frontend(name);
129 : GenerateStoreViaSetter(masm(), map(), receiver(), holder, accessor_index,
130 36128 : expected_arguments, scratch2());
131 :
132 18064 : return GetCode(kind(), name);
133 : }
134 :
135 70 : Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
136 : Handle<JSObject> object, Handle<Name> name,
137 : const CallOptimization& call_optimization, int accessor_index,
138 : Handle<Code> slow_stub) {
139 70 : if (V8_UNLIKELY(FLAG_runtime_stats)) {
140 140 : GenerateTailCall(masm(), slow_stub);
141 : }
142 70 : Register holder = Frontend(name);
143 : if (Descriptor::kPassLastArgsOnStack) {
144 : __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue);
145 : }
146 : GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()),
147 : receiver(), scratch2(), true, value(), holder,
148 140 : accessor_index);
149 70 : return GetCode(kind(), name);
150 : }
151 :
152 :
153 : #undef __
154 :
155 : } // namespace internal
156 : } // namespace v8
|