V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
code-stubs.cc
1 // Copyright 2012 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/code-stubs.h"
6 
7 #include <sstream>
8 
9 #include "src/arguments.h"
10 #include "src/assembler-inl.h"
11 #include "src/ast/ast.h"
12 #include "src/bootstrapper.h"
13 #include "src/code-factory.h"
14 #include "src/code-stubs-utils.h"
15 #include "src/code-tracer.h"
16 #include "src/counters.h"
17 #include "src/gdb-jit.h"
18 #include "src/heap/heap-inl.h"
19 #include "src/ic/ic-stats.h"
20 #include "src/ic/ic.h"
21 #include "src/macro-assembler.h"
22 #include "src/objects-inl.h"
23 #include "src/objects/hash-table-inl.h"
24 #include "src/tracing/tracing-category-observer.h"
25 
26 namespace v8 {
27 namespace internal {
28 
29 using compiler::CodeAssemblerState;
30 
31 CodeStubDescriptor::CodeStubDescriptor(CodeStub* stub)
32  : isolate_(stub->isolate()),
33  call_descriptor_(stub->GetCallInterfaceDescriptor()),
34  stack_parameter_count_(no_reg),
35  hint_stack_parameter_count_(-1),
36  function_mode_(NOT_JS_FUNCTION_STUB_MODE),
37  deoptimization_handler_(kNullAddress),
38  miss_handler_(),
39  has_miss_handler_(false) {}
40 
41 CodeStubDescriptor::CodeStubDescriptor(Isolate* isolate, uint32_t stub_key)
42  : isolate_(isolate),
43  stack_parameter_count_(no_reg),
44  hint_stack_parameter_count_(-1),
45  function_mode_(NOT_JS_FUNCTION_STUB_MODE),
46  deoptimization_handler_(kNullAddress),
47  miss_handler_(),
48  has_miss_handler_(false) {
49  CodeStub::InitializeDescriptor(isolate, stub_key, this);
50 }
51 
52 
53 void CodeStubDescriptor::Initialize(Address deoptimization_handler,
54  int hint_stack_parameter_count,
55  StubFunctionMode function_mode) {
56  deoptimization_handler_ = deoptimization_handler;
57  hint_stack_parameter_count_ = hint_stack_parameter_count;
58  function_mode_ = function_mode;
59 }
60 
61 
62 void CodeStubDescriptor::Initialize(Register stack_parameter_count,
63  Address deoptimization_handler,
64  int hint_stack_parameter_count,
65  StubFunctionMode function_mode) {
66  Initialize(deoptimization_handler, hint_stack_parameter_count, function_mode);
67  stack_parameter_count_ = stack_parameter_count;
68 }
69 
70 bool CodeStub::FindCodeInCache(Code* code_out) {
71  SimpleNumberDictionary stubs = isolate()->heap()->code_stubs();
72  int index = stubs->FindEntry(isolate(), GetKey());
73  if (index != SimpleNumberDictionary::kNotFound) {
74  *code_out = Code::cast(stubs->ValueAt(index));
75  return true;
76  }
77  return false;
78 }
79 
80 
81 void CodeStub::RecordCodeGeneration(Handle<Code> code) {
82  std::ostringstream os;
83  os << *this;
84  PROFILE(isolate(),
85  CodeCreateEvent(CodeEventListener::STUB_TAG,
86  AbstractCode::cast(*code), os.str().c_str()));
87  Counters* counters = isolate()->counters();
88  counters->total_stubs_code_size()->Increment(code->raw_instruction_size());
89 #ifdef DEBUG
90  code->VerifyEmbeddedObjects(isolate());
91 #endif
92 }
93 
94 
95 void CodeStub::DeleteStubFromCacheForTesting() {
96  Heap* heap = isolate_->heap();
97  Handle<SimpleNumberDictionary> dict(heap->code_stubs(), isolate());
98  int entry = dict->FindEntry(isolate(), GetKey());
99  DCHECK_NE(SimpleNumberDictionary::kNotFound, entry);
100  dict = SimpleNumberDictionary::DeleteEntry(isolate(), dict, entry);
101  heap->SetRootCodeStubs(*dict);
102 }
103 
104 Handle<Code> PlatformCodeStub::GenerateCode() {
105  Factory* factory = isolate()->factory();
106 
107  // Generate the new code.
108  // TODO(yangguo): remove this once we can serialize IC stubs.
109  AssemblerOptions options = AssemblerOptions::Default(isolate(), true);
110  MacroAssembler masm(isolate(), options, nullptr, 256,
111  CodeObjectRequired::kYes);
112 
113  {
114  // Update the static counter each time a new code stub is generated.
115  isolate()->counters()->code_stubs()->Increment();
116 
117  // Generate the code for the stub.
118  NoCurrentFrameScope scope(&masm);
119  Generate(&masm);
120  }
121 
122  // Generate the handler table.
123  int handler_table_offset = GenerateHandlerTable(&masm);
124 
125  // Create the code object.
126  CodeDesc desc;
127  masm.GetCode(isolate(), &desc);
128  // Copy the generated code into a heap object.
129  Handle<Code> new_object = factory->NewCode(
130  desc, Code::STUB, masm.CodeObject(), Builtins::kNoBuiltinId,
131  MaybeHandle<ByteArray>(), DeoptimizationData::Empty(isolate()),
132  NeedsImmovableCode(), GetKey(), false, 0, 0, handler_table_offset);
133  return new_object;
134 }
135 
136 
137 Handle<Code> CodeStub::GetCode() {
138  Heap* heap = isolate()->heap();
139  Code code;
140  if (FindCodeInCache(&code)) {
141  DCHECK(code->is_stub());
142  return handle(code, isolate_);
143  }
144 
145  {
146  HandleScope scope(isolate());
147  // Canonicalize handles, so that we can share constant pool entries pointing
148  // to code targets without dereferencing their handles.
149  CanonicalHandleScope canonical(isolate());
150 
151  Handle<Code> new_object = GenerateCode();
152  DCHECK_EQ(GetKey(), new_object->stub_key());
153  RecordCodeGeneration(new_object);
154 
155 #ifdef ENABLE_DISASSEMBLER
156  if (FLAG_print_code_stubs) {
157  CodeTracer::Scope trace_scope(isolate()->GetCodeTracer());
158  OFStream os(trace_scope.file());
159  std::ostringstream name;
160  name << *this;
161  new_object->Disassemble(name.str().c_str(), os);
162  os << "\n";
163  }
164 #endif
165 
166  // Update the dictionary and the root in Heap.
167  Handle<SimpleNumberDictionary> dict = SimpleNumberDictionary::Set(
168  isolate(), handle(heap->code_stubs(), isolate_), GetKey(), new_object);
169  heap->SetRootCodeStubs(*dict);
170  code = *new_object;
171  }
172 
173  DCHECK(!NeedsImmovableCode() || heap->IsImmovable(code));
174  return Handle<Code>(code, isolate());
175 }
176 
177 CodeStub::Major CodeStub::GetMajorKey(const Code code_stub) {
178  return MajorKeyFromKey(code_stub->stub_key());
179 }
180 
181 const char* CodeStub::MajorName(CodeStub::Major major_key) {
182  switch (major_key) {
183 #define DEF_CASE(name) case name: return #name "Stub";
184  CODE_STUB_LIST(DEF_CASE)
185 #undef DEF_CASE
186  case NoCache:
187  return "<NoCache>Stub";
188  case NUMBER_OF_IDS:
189  UNREACHABLE();
190  }
191  return nullptr;
192 }
193 
194 
195 void CodeStub::PrintBaseName(std::ostream& os) const { // NOLINT
196  os << MajorName(MajorKey());
197 }
198 
199 
200 void CodeStub::PrintName(std::ostream& os) const { // NOLINT
201  PrintBaseName(os);
202  PrintState(os);
203 }
204 
205 
206 void CodeStub::Dispatch(Isolate* isolate, uint32_t key, void** value_out,
207  DispatchedCall call) {
208  switch (MajorKeyFromKey(key)) {
209 #define DEF_CASE(NAME) \
210  case NAME: { \
211  NAME##Stub stub(key, isolate); \
212  CodeStub* pstub = &stub; \
213  call(pstub, value_out); \
214  break; \
215  }
216  CODE_STUB_LIST(DEF_CASE)
217 #undef DEF_CASE
218  case NUMBER_OF_IDS:
219  case NoCache:
220  UNREACHABLE();
221  break;
222  }
223 }
224 
225 int PlatformCodeStub::GenerateHandlerTable(MacroAssembler* masm) { return 0; }
226 
227 static void InitializeDescriptorDispatchedCall(CodeStub* stub,
228  void** value_out) {
229  CodeStubDescriptor* descriptor_out =
230  reinterpret_cast<CodeStubDescriptor*>(value_out);
231  descriptor_out->set_call_descriptor(stub->GetCallInterfaceDescriptor());
232 }
233 
234 
235 void CodeStub::InitializeDescriptor(Isolate* isolate, uint32_t key,
236  CodeStubDescriptor* desc) {
237  void** value_out = reinterpret_cast<void**>(desc);
238  Dispatch(isolate, key, value_out, &InitializeDescriptorDispatchedCall);
239 }
240 
241 
242 void CodeStub::GetCodeDispatchCall(CodeStub* stub, void** value_out) {
243  Handle<Code>* code_out = reinterpret_cast<Handle<Code>*>(value_out);
244  *code_out = stub->GetCode();
245 }
246 
247 
248 MaybeHandle<Code> CodeStub::GetCode(Isolate* isolate, uint32_t key) {
249  HandleScope scope(isolate);
250  Handle<Code> code;
251  void** value_out = reinterpret_cast<void**>(&code);
252  Dispatch(isolate, key, value_out, &GetCodeDispatchCall);
253  return scope.CloseAndEscape(code);
254 }
255 
256 int JSEntryStub::GenerateHandlerTable(MacroAssembler* masm) {
257  int handler_table_offset = HandlerTable::EmitReturnTableStart(masm, 1);
258  HandlerTable::EmitReturnEntry(masm, 0, handler_offset_);
259  return handler_table_offset;
260 }
261 
262 } // namespace internal
263 } // namespace v8
Definition: libplatform.h:13