code-stubs.cc revision 8a31eba00023874d4a1dcdc5f411cc4336776874
1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "bootstrapper.h"
31#include "code-stubs.h"
32#include "factory.h"
33#include "macro-assembler.h"
34#include "oprofile-agent.h"
35
36namespace v8 {
37namespace internal {
38
39bool CodeStub::FindCodeInCache(Code** code_out) {
40  int index = Heap::code_stubs()->FindEntry(GetKey());
41  if (index != NumberDictionary::kNotFound) {
42    *code_out = Code::cast(Heap::code_stubs()->ValueAt(index));
43    return true;
44  }
45  return false;
46}
47
48
49void CodeStub::GenerateCode(MacroAssembler* masm) {
50  // Update the static counter each time a new code stub is generated.
51  Counters::code_stubs.Increment();
52  // Nested stubs are not allowed for leafs.
53  masm->set_allow_stub_calls(AllowsStubCalls());
54  // Generate the code for the stub.
55  masm->set_generating_stub(true);
56  Generate(masm);
57}
58
59
60void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
61  code->set_major_key(MajorKey());
62
63  OPROFILE(CreateNativeCodeRegion(GetName(),
64                                  code->instruction_start(),
65                                  code->instruction_size()));
66  PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
67  Counters::total_stubs_code_size.Increment(code->instruction_size());
68
69#ifdef ENABLE_DISASSEMBLER
70  if (FLAG_print_code_stubs) {
71#ifdef DEBUG
72    Print();
73#endif
74    code->Disassemble(GetName());
75    PrintF("\n");
76  }
77#endif
78}
79
80
81int CodeStub::GetCodeKind() {
82  return Code::STUB;
83}
84
85
86Handle<Code> CodeStub::GetCode() {
87  Code* code;
88  if (!FindCodeInCache(&code)) {
89    v8::HandleScope scope;
90
91    // Generate the new code.
92    MacroAssembler masm(NULL, 256);
93    GenerateCode(&masm);
94
95    // Create the code object.
96    CodeDesc desc;
97    masm.GetCode(&desc);
98
99    // Copy the generated code into a heap object.
100    Code::Flags flags = Code::ComputeFlags(
101        static_cast<Code::Kind>(GetCodeKind()),
102        InLoop(),
103        GetICState());
104    Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
105    RecordCodeGeneration(*new_object, &masm);
106
107    // Update the dictionary and the root in Heap.
108    Handle<NumberDictionary> dict =
109        Factory::DictionaryAtNumberPut(
110            Handle<NumberDictionary>(Heap::code_stubs()),
111            GetKey(),
112            new_object);
113    Heap::public_set_code_stubs(*dict);
114
115    code = *new_object;
116  }
117
118  return Handle<Code>(code);
119}
120
121
122MaybeObject* CodeStub::TryGetCode() {
123  Code* code;
124  if (!FindCodeInCache(&code)) {
125    // Generate the new code.
126    MacroAssembler masm(NULL, 256);
127    GenerateCode(&masm);
128
129    // Create the code object.
130    CodeDesc desc;
131    masm.GetCode(&desc);
132
133    // Try to copy the generated code into a heap object.
134    Code::Flags flags = Code::ComputeFlags(
135        static_cast<Code::Kind>(GetCodeKind()),
136        InLoop(),
137        GetICState());
138    Object* new_object;
139    { MaybeObject* maybe_new_object =
140          Heap::CreateCode(desc, flags, masm.CodeObject());
141      if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
142    }
143    code = Code::cast(new_object);
144    RecordCodeGeneration(code, &masm);
145
146    // Try to update the code cache but do not fail if unable.
147    MaybeObject* maybe_new_object =
148        Heap::code_stubs()->AtNumberPut(GetKey(), code);
149    if (maybe_new_object->ToObject(&new_object)) {
150      Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
151    }
152  }
153
154  return code;
155}
156
157
158const char* CodeStub::MajorName(CodeStub::Major major_key,
159                                bool allow_unknown_keys) {
160  switch (major_key) {
161#define DEF_CASE(name) case name: return #name;
162    CODE_STUB_LIST(DEF_CASE)
163#undef DEF_CASE
164    default:
165      if (!allow_unknown_keys) {
166        UNREACHABLE();
167      }
168      return NULL;
169  }
170}
171
172
173} }  // namespace v8::internal
174