code-stubs.cc revision b0fe1620dcb4135ac3ab2d66ff93072373911299
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    FinishCode(*new_object);
107
108    // Update the dictionary and the root in Heap.
109    Handle<NumberDictionary> dict =
110        Factory::DictionaryAtNumberPut(
111            Handle<NumberDictionary>(Heap::code_stubs()),
112            GetKey(),
113            new_object);
114    Heap::public_set_code_stubs(*dict);
115
116    code = *new_object;
117  }
118
119  return Handle<Code>(code);
120}
121
122
123MaybeObject* CodeStub::TryGetCode() {
124  Code* code;
125  if (!FindCodeInCache(&code)) {
126    // Generate the new code.
127    MacroAssembler masm(NULL, 256);
128    GenerateCode(&masm);
129
130    // Create the code object.
131    CodeDesc desc;
132    masm.GetCode(&desc);
133
134    // Try to copy the generated code into a heap object.
135    Code::Flags flags = Code::ComputeFlags(
136        static_cast<Code::Kind>(GetCodeKind()),
137        InLoop(),
138        GetICState());
139    Object* new_object;
140    { MaybeObject* maybe_new_object =
141          Heap::CreateCode(desc, flags, masm.CodeObject());
142      if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
143    }
144    code = Code::cast(new_object);
145    RecordCodeGeneration(code, &masm);
146    FinishCode(code);
147
148    // Try to update the code cache but do not fail if unable.
149    MaybeObject* maybe_new_object =
150        Heap::code_stubs()->AtNumberPut(GetKey(), code);
151    if (maybe_new_object->ToObject(&new_object)) {
152      Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
153    }
154  }
155
156  return code;
157}
158
159
160const char* CodeStub::MajorName(CodeStub::Major major_key,
161                                bool allow_unknown_keys) {
162  switch (major_key) {
163#define DEF_CASE(name) case name: return #name;
164    CODE_STUB_LIST(DEF_CASE)
165#undef DEF_CASE
166    default:
167      if (!allow_unknown_keys) {
168        UNREACHABLE();
169      }
170      return NULL;
171  }
172}
173
174
175int ICCompareStub::MinorKey() {
176  return OpField::encode(op_ - Token::EQ) | StateField::encode(state_);
177}
178
179
180void ICCompareStub::Generate(MacroAssembler* masm) {
181  switch (state_) {
182    case CompareIC::UNINITIALIZED:
183      GenerateMiss(masm);
184      break;
185    case CompareIC::SMIS:
186      GenerateSmis(masm);
187      break;
188    case CompareIC::HEAP_NUMBERS:
189      GenerateHeapNumbers(masm);
190      break;
191    case CompareIC::OBJECTS:
192      GenerateObjects(masm);
193      break;
194    default:
195      UNREACHABLE();
196  }
197}
198
199
200} }  // namespace v8::internal
201