blob: 1b0d8b0b6fb8386f1df145cae18d51b33b270fba [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// 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"
Andrei Popescu402d9372010-02-26 13:31:12 +000034#include "oprofile-agent.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000035
36namespace v8 {
37namespace internal {
38
Leon Clarkee46be812010-01-19 14:06:41 +000039bool CodeStub::FindCodeInCache(Code** code_out) {
Leon Clarkee46be812010-01-19 14:06:41 +000040 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;
Steve Blockd0582a62009-12-15 09:54:21 +000044 }
Leon Clarkee46be812010-01-19 14:06:41 +000045 return false;
46}
Steve Blockd0582a62009-12-15 09:54:21 +000047
Leon Clarkee46be812010-01-19 14:06:41 +000048
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
Steve Block6ded16b2010-05-10 14:33:55 +010063 OPROFILE(CreateNativeCodeRegion(GetName(),
64 code->instruction_start(),
65 code->instruction_size()));
66 PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, GetName()));
Leon Clarkee46be812010-01-19 14:06:41 +000067 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
Steve Block6ded16b2010-05-10 14:33:55 +010081int CodeStub::GetCodeKind() {
82 return Code::STUB;
83}
84
85
Leon Clarkee46be812010-01-19 14:06:41 +000086Handle<Code> CodeStub::GetCode() {
87 Code* code;
88 if (!FindCodeInCache(&code)) {
Steve Blockd0582a62009-12-15 09:54:21 +000089 v8::HandleScope scope;
Steve Blocka7e24c12009-10-30 11:49:00 +000090
Steve Blocka7e24c12009-10-30 11:49:00 +000091 // Generate the new code.
92 MacroAssembler masm(NULL, 256);
Leon Clarkee46be812010-01-19 14:06:41 +000093 GenerateCode(&masm);
Steve Blocka7e24c12009-10-30 11:49:00 +000094
95 // Create the code object.
96 CodeDesc desc;
97 masm.GetCode(&desc);
98
Leon Clarkee46be812010-01-19 14:06:41 +000099 // Copy the generated code into a heap object.
Steve Block6ded16b2010-05-10 14:33:55 +0100100 Code::Flags flags = Code::ComputeFlags(
101 static_cast<Code::Kind>(GetCodeKind()),
102 InLoop(),
103 GetICState());
Ben Murdoch3bec4d22010-07-22 14:51:16 +0100104 Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
Leon Clarkee46be812010-01-19 14:06:41 +0000105 RecordCodeGeneration(*new_object, &masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100106 FinishCode(*new_object);
Steve Blocka7e24c12009-10-30 11:49:00 +0000107
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800108 // 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
Leon Clarkee46be812010-01-19 14:06:41 +0000116 code = *new_object;
Steve Blocka7e24c12009-10-30 11:49:00 +0000117 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000118
Leon Clarkee46be812010-01-19 14:06:41 +0000119 return Handle<Code>(code);
120}
121
122
John Reck59135872010-11-02 12:39:01 -0700123MaybeObject* CodeStub::TryGetCode() {
Leon Clarkee46be812010-01-19 14:06:41 +0000124 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.
Steve Block6ded16b2010-05-10 14:33:55 +0100135 Code::Flags flags = Code::ComputeFlags(
136 static_cast<Code::Kind>(GetCodeKind()),
137 InLoop(),
138 GetICState());
John Reck59135872010-11-02 12:39:01 -0700139 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 }
Leon Clarkee46be812010-01-19 14:06:41 +0000144 code = Code::cast(new_object);
145 RecordCodeGeneration(code, &masm);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100146 FinishCode(code);
Leon Clarkee46be812010-01-19 14:06:41 +0000147
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800148 // 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));
Leon Clarkee46be812010-01-19 14:06:41 +0000153 }
154 }
155
156 return code;
Steve Blocka7e24c12009-10-30 11:49:00 +0000157}
158
159
Andrei Popescu31002712010-02-23 13:46:05 +0000160const char* CodeStub::MajorName(CodeStub::Major major_key,
161 bool allow_unknown_keys) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000162 switch (major_key) {
Steve Blockd0582a62009-12-15 09:54:21 +0000163#define DEF_CASE(name) case name: return #name;
164 CODE_STUB_LIST(DEF_CASE)
165#undef DEF_CASE
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 default:
Andrei Popescu31002712010-02-23 13:46:05 +0000167 if (!allow_unknown_keys) {
168 UNREACHABLE();
169 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 return NULL;
171 }
172}
173
174
Ben Murdochb0fe1622011-05-05 13:52:32 +0100175int 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
Steve Blocka7e24c12009-10-30 11:49:00 +0000200} } // namespace v8::internal