blob: 787ec2a7a1ee2d8d0b37d522d6453c4e2a93803b [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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"
ager@chromium.org5c838252010-02-19 08:53:10 +000034#include "oprofile-agent.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000035
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000039bool CodeStub::FindCodeInCache(Code** code_out) {
40 if (has_custom_cache()) return GetCustomCache(code_out);
41 int index = Heap::code_stubs()->FindEntry(GetKey());
42 if (index != NumberDictionary::kNotFound) {
43 *code_out = Code::cast(Heap::code_stubs()->ValueAt(index));
44 return true;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000045 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000046 return false;
47}
ager@chromium.orgc4c92722009-11-18 14:12:51 +000048
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000049
50void CodeStub::GenerateCode(MacroAssembler* masm) {
51 // Update the static counter each time a new code stub is generated.
52 Counters::code_stubs.Increment();
53 // Nested stubs are not allowed for leafs.
54 masm->set_allow_stub_calls(AllowsStubCalls());
55 // Generate the code for the stub.
56 masm->set_generating_stub(true);
57 Generate(masm);
58}
59
60
61void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
62 code->set_major_key(MajorKey());
63
ager@chromium.orgb26c50a2010-03-26 09:27:16 +000064 OPROFILE(CreateNativeCodeRegion(GetName(),
65 code->instruction_start(),
66 code->instruction_size()));
lrn@chromium.org25156de2010-04-06 13:10:27 +000067 PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000068 Counters::total_stubs_code_size.Increment(code->instruction_size());
69
70#ifdef ENABLE_DISASSEMBLER
71 if (FLAG_print_code_stubs) {
72#ifdef DEBUG
73 Print();
74#endif
75 code->Disassemble(GetName());
76 PrintF("\n");
77 }
78#endif
79}
80
81
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000082int CodeStub::GetCodeKind() {
83 return Code::STUB;
84}
85
86
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000087Handle<Code> CodeStub::GetCode() {
88 Code* code;
89 if (!FindCodeInCache(&code)) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +000090 v8::HandleScope scope;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000092 // Generate the new code.
93 MacroAssembler masm(NULL, 256);
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +000094 GenerateCode(&masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000095
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096 // Create the code object.
97 CodeDesc desc;
98 masm.GetCode(&desc);
99
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000100 // Copy the generated code into a heap object.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000101 Code::Flags flags = Code::ComputeFlags(
102 static_cast<Code::Kind>(GetCodeKind()),
103 InLoop(),
104 GetICState());
ager@chromium.org6a2b0aa2010-07-13 20:58:03 +0000105 Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000106 RecordCodeGeneration(*new_object, &masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000107
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000108 if (has_custom_cache()) {
109 SetCustomCache(*new_object);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000110 } else {
111 // Update the dictionary and the root in Heap.
112 Handle<NumberDictionary> dict =
113 Factory::DictionaryAtNumberPut(
114 Handle<NumberDictionary>(Heap::code_stubs()),
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000115 GetKey(),
116 new_object);
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000117 Heap::public_set_code_stubs(*dict);
118 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000119 code = *new_object;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000121
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000122 return Handle<Code>(code);
123}
124
125
lrn@chromium.org303ada72010-10-27 09:33:13 +0000126MaybeObject* CodeStub::TryGetCode() {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000127 Code* code;
128 if (!FindCodeInCache(&code)) {
129 // Generate the new code.
130 MacroAssembler masm(NULL, 256);
131 GenerateCode(&masm);
132
133 // Create the code object.
134 CodeDesc desc;
135 masm.GetCode(&desc);
136
137 // Try to copy the generated code into a heap object.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000138 Code::Flags flags = Code::ComputeFlags(
139 static_cast<Code::Kind>(GetCodeKind()),
140 InLoop(),
141 GetICState());
lrn@chromium.org303ada72010-10-27 09:33:13 +0000142 Object* new_object;
143 { MaybeObject* maybe_new_object =
144 Heap::CreateCode(desc, flags, masm.CodeObject());
145 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
146 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000147 code = Code::cast(new_object);
148 RecordCodeGeneration(code, &masm);
149
150 if (has_custom_cache()) {
151 SetCustomCache(code);
152 } else {
153 // Try to update the code cache but do not fail if unable.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000154 MaybeObject* maybe_new_object =
155 Heap::code_stubs()->AtNumberPut(GetKey(), code);
156 if (maybe_new_object->ToObject(&new_object)) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000157 Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
158 }
159 }
160 }
161
162 return code;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000163}
164
165
ager@chromium.org5c838252010-02-19 08:53:10 +0000166const char* CodeStub::MajorName(CodeStub::Major major_key,
167 bool allow_unknown_keys) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000168 switch (major_key) {
ager@chromium.org3811b432009-10-28 14:53:37 +0000169#define DEF_CASE(name) case name: return #name;
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000170 CODE_STUB_LIST(DEF_CASE)
ager@chromium.org3811b432009-10-28 14:53:37 +0000171#undef DEF_CASE
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000172 default:
ager@chromium.org5c838252010-02-19 08:53:10 +0000173 if (!allow_unknown_keys) {
174 UNREACHABLE();
175 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000176 return NULL;
177 }
178}
179
180
181} } // namespace v8::internal