| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 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" | 
| Andrei Popescu | 402d937 | 2010-02-26 13:31:12 +0000 | [diff] [blame^] | 34 | #include "oprofile-agent.h" | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 35 |  | 
|  | 36 | namespace v8 { | 
|  | 37 | namespace internal { | 
|  | 38 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 39 | bool 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; | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 45 | } | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 46 | return false; | 
|  | 47 | } | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 48 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 49 |  | 
|  | 50 | void 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 |  | 
|  | 61 | void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) { | 
|  | 62 | code->set_major_key(MajorKey()); | 
|  | 63 |  | 
| Andrei Popescu | 402d937 | 2010-02-26 13:31:12 +0000 | [diff] [blame^] | 64 | #ifdef ENABLE_OPROFILE_AGENT | 
|  | 65 | // Register the generated stub with the OPROFILE agent. | 
|  | 66 | OProfileAgent::CreateNativeCodeRegion(GetName(), | 
|  | 67 | code->instruction_start(), | 
|  | 68 | code->instruction_size()); | 
|  | 69 | #endif | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 70 |  | 
|  | 71 | LOG(CodeCreateEvent(Logger::STUB_TAG, code, GetName())); | 
|  | 72 | Counters::total_stubs_code_size.Increment(code->instruction_size()); | 
|  | 73 |  | 
|  | 74 | #ifdef ENABLE_DISASSEMBLER | 
|  | 75 | if (FLAG_print_code_stubs) { | 
|  | 76 | #ifdef DEBUG | 
|  | 77 | Print(); | 
|  | 78 | #endif | 
|  | 79 | code->Disassemble(GetName()); | 
|  | 80 | PrintF("\n"); | 
|  | 81 | } | 
|  | 82 | #endif | 
|  | 83 | } | 
|  | 84 |  | 
|  | 85 |  | 
|  | 86 | Handle<Code> CodeStub::GetCode() { | 
|  | 87 | Code* code; | 
|  | 88 | if (!FindCodeInCache(&code)) { | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 89 | v8::HandleScope scope; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 90 |  | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 91 | // Generate the new code. | 
|  | 92 | MacroAssembler masm(NULL, 256); | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 93 | GenerateCode(&masm); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 94 |  | 
|  | 95 | // Create the code object. | 
|  | 96 | CodeDesc desc; | 
|  | 97 | masm.GetCode(&desc); | 
|  | 98 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 99 | // Copy the generated code into a heap object. | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 100 | Code::Flags flags = Code::ComputeFlags(Code::STUB, InLoop()); | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 101 | Handle<Code> new_object = | 
|  | 102 | Factory::NewCode(desc, NULL, flags, masm.CodeObject()); | 
|  | 103 | RecordCodeGeneration(*new_object, &masm); | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 104 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 105 | if (has_custom_cache()) { | 
|  | 106 | SetCustomCache(*new_object); | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 107 | } else { | 
|  | 108 | // Update the dictionary and the root in Heap. | 
|  | 109 | Handle<NumberDictionary> dict = | 
|  | 110 | Factory::DictionaryAtNumberPut( | 
|  | 111 | Handle<NumberDictionary>(Heap::code_stubs()), | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 112 | GetKey(), | 
|  | 113 | new_object); | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 114 | Heap::public_set_code_stubs(*dict); | 
|  | 115 | } | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 116 | code = *new_object; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 117 | } | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 118 |  | 
| Leon Clarke | e46be81 | 2010-01-19 14:06:41 +0000 | [diff] [blame] | 119 | return Handle<Code>(code); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 |  | 
|  | 123 | Object* 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(Code::STUB, InLoop()); | 
|  | 136 | Object* new_object = | 
|  | 137 | Heap::CreateCode(desc, NULL, flags, masm.CodeObject()); | 
|  | 138 | if (new_object->IsFailure()) return new_object; | 
|  | 139 | code = Code::cast(new_object); | 
|  | 140 | RecordCodeGeneration(code, &masm); | 
|  | 141 |  | 
|  | 142 | if (has_custom_cache()) { | 
|  | 143 | SetCustomCache(code); | 
|  | 144 | } else { | 
|  | 145 | // Try to update the code cache but do not fail if unable. | 
|  | 146 | new_object = Heap::code_stubs()->AtNumberPut(GetKey(), code); | 
|  | 147 | if (!new_object->IsFailure()) { | 
|  | 148 | Heap::public_set_code_stubs(NumberDictionary::cast(new_object)); | 
|  | 149 | } | 
|  | 150 | } | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 | return code; | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 154 | } | 
|  | 155 |  | 
|  | 156 |  | 
| Andrei Popescu | 3100271 | 2010-02-23 13:46:05 +0000 | [diff] [blame] | 157 | const char* CodeStub::MajorName(CodeStub::Major major_key, | 
|  | 158 | bool allow_unknown_keys) { | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 159 | switch (major_key) { | 
| Steve Block | d0582a6 | 2009-12-15 09:54:21 +0000 | [diff] [blame] | 160 | #define DEF_CASE(name) case name: return #name; | 
|  | 161 | CODE_STUB_LIST(DEF_CASE) | 
|  | 162 | #undef DEF_CASE | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 163 | default: | 
| Andrei Popescu | 3100271 | 2010-02-23 13:46:05 +0000 | [diff] [blame] | 164 | if (!allow_unknown_keys) { | 
|  | 165 | UNREACHABLE(); | 
|  | 166 | } | 
| Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 167 | return NULL; | 
|  | 168 | } | 
|  | 169 | } | 
|  | 170 |  | 
|  | 171 |  | 
|  | 172 | } }  // namespace v8::internal |