OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 | 142 |
143 | 143 |
144 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { | 144 void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { |
145 // ----------- S t a t e ------------- | 145 // ----------- S t a t e ------------- |
146 // -- a0 : number of arguments | 146 // -- a0 : number of arguments |
147 // -- a1 : constructor function | 147 // -- a1 : constructor function |
148 // -- ra : return address | 148 // -- ra : return address |
149 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) | 149 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) |
150 // -- sp[argc * 4] : receiver | 150 // -- sp[argc * 4] : receiver |
151 // ----------------------------------- | 151 // ----------------------------------- |
152 Counters* counters = masm->isolate()->counters(); | |
153 __ IncrementCounter(counters->string_ctor_calls(), 1, a2, a3); | |
154 | 152 |
155 Register function = a1; | 153 // 1. Load the first argument into a0 and get rid of the rest (including the |
156 if (FLAG_debug_code) { | 154 // receiver). |
157 __ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, a2); | 155 { |
158 __ Assert(eq, kUnexpectedStringFunction, function, Operand(a2)); | 156 Label no_arguments, done; |
| 157 __ Branch(&no_arguments, eq, a0, Operand(zero_reg)); |
| 158 __ Subu(a0, a0, Operand(1)); |
| 159 __ sll(a0, a0, kPointerSizeLog2); |
| 160 __ Addu(sp, a0, sp); |
| 161 __ lw(a0, MemOperand(sp)); |
| 162 __ Drop(2); |
| 163 __ jmp(&done); |
| 164 __ bind(&no_arguments); |
| 165 __ LoadRoot(a0, Heap::kempty_stringRootIndex); |
| 166 __ Drop(1); |
| 167 __ bind(&done); |
159 } | 168 } |
160 | 169 |
161 // Load the first arguments in a0 and get rid of the rest. | 170 // 2. Make sure a0 is a string. |
162 Label no_arguments; | 171 { |
163 __ Branch(&no_arguments, eq, a0, Operand(zero_reg)); | 172 Label convert, done_convert; |
164 // First args = sp[(argc - 1) * 4]. | 173 __ JumpIfSmi(a0, &convert); |
165 __ Subu(a0, a0, Operand(1)); | 174 __ GetObjectType(a0, a2, a2); |
166 __ sll(a0, a0, kPointerSizeLog2); | 175 __ And(t0, a2, Operand(kIsNotStringMask)); |
167 __ Addu(sp, a0, sp); | 176 __ Branch(&done_convert, eq, t0, Operand(zero_reg)); |
168 __ lw(a0, MemOperand(sp)); | 177 __ bind(&convert); |
169 // sp now point to args[0], drop args[0] + receiver. | 178 { |
170 __ Drop(2); | 179 FrameScope scope(masm, StackFrame::INTERNAL); |
| 180 ToStringStub stub(masm->isolate()); |
| 181 __ Push(a1); |
| 182 __ CallStub(&stub); |
| 183 __ Move(a0, v0); |
| 184 __ Pop(a1); |
| 185 } |
| 186 __ bind(&done_convert); |
| 187 } |
171 | 188 |
172 Register argument = a2; | 189 // 3. Allocate a JSValue wrapper for the string. |
173 Label not_cached, argument_is_string; | 190 { |
174 __ LookupNumberStringCache(a0, // Input. | 191 // ----------- S t a t e ------------- |
175 argument, // Result. | 192 // -- a0 : the first argument |
176 a3, // Scratch. | 193 // -- a1 : constructor function |
177 t0, // Scratch. | 194 // -- ra : return address |
178 t1, // Scratch. | 195 // ----------------------------------- |
179 ¬_cached); | |
180 __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, t0); | |
181 __ bind(&argument_is_string); | |
182 | 196 |
183 // ----------- S t a t e ------------- | 197 Label allocate, done_allocate; |
184 // -- a2 : argument converted to string | 198 __ Allocate(JSValue::kSize, v0, a2, a3, &allocate, TAG_OBJECT); |
185 // -- a1 : constructor function | 199 __ bind(&done_allocate); |
186 // -- ra : return address | |
187 // ----------------------------------- | |
188 | 200 |
189 Label gc_required; | 201 // Initialize the JSValue in eax. |
190 __ Allocate(JSValue::kSize, | 202 __ LoadGlobalFunctionInitialMap(a1, a2, a3); |
191 v0, // Result. | 203 __ sw(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); |
192 a3, // Scratch. | 204 __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); |
193 t0, // Scratch. | 205 __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
194 &gc_required, | 206 __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); |
195 TAG_OBJECT); | 207 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); |
| 208 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| 209 __ Ret(); |
196 | 210 |
197 // Initialising the String Object. | 211 // Fallback to the runtime to allocate in new space. |
198 Register map = a3; | 212 __ bind(&allocate); |
199 __ LoadGlobalFunctionInitialMap(function, map, t0); | 213 { |
200 if (FLAG_debug_code) { | 214 FrameScope scope(masm, StackFrame::INTERNAL); |
201 __ lbu(t0, FieldMemOperand(map, Map::kInstanceSizeOffset)); | 215 __ Move(a2, Smi::FromInt(JSValue::kSize)); |
202 __ Assert(eq, kUnexpectedStringWrapperInstanceSize, | 216 __ Push(a0, a1, a2); |
203 t0, Operand(JSValue::kSize >> kPointerSizeLog2)); | 217 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
204 __ lbu(t0, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); | 218 __ Pop(a0, a1); |
205 __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper, | 219 } |
206 t0, Operand(zero_reg)); | 220 __ jmp(&done_allocate); |
207 } | 221 } |
208 __ sw(map, FieldMemOperand(v0, HeapObject::kMapOffset)); | |
209 | |
210 __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); | |
211 __ sw(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | |
212 __ sw(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); | |
213 | |
214 __ sw(argument, FieldMemOperand(v0, JSValue::kValueOffset)); | |
215 | |
216 // Ensure the object is fully initialized. | |
217 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); | |
218 | |
219 __ Ret(); | |
220 | |
221 // The argument was not found in the number to string cache. Check | |
222 // if it's a string already before calling the conversion builtin. | |
223 Label convert_argument; | |
224 __ bind(¬_cached); | |
225 __ JumpIfSmi(a0, &convert_argument); | |
226 | |
227 // Is it a String? | |
228 __ lw(a2, FieldMemOperand(a0, HeapObject::kMapOffset)); | |
229 __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset)); | |
230 STATIC_ASSERT(kNotStringTag != 0); | |
231 __ And(t0, a3, Operand(kIsNotStringMask)); | |
232 __ Branch(&convert_argument, ne, t0, Operand(zero_reg)); | |
233 __ mov(argument, a0); | |
234 __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0); | |
235 __ Branch(&argument_is_string); | |
236 | |
237 // Invoke the conversion builtin and put the result into a2. | |
238 __ bind(&convert_argument); | |
239 __ push(function); // Preserve the function. | |
240 __ IncrementCounter(counters->string_ctor_conversions(), 1, a3, t0); | |
241 { | |
242 FrameScope scope(masm, StackFrame::INTERNAL); | |
243 ToStringStub stub(masm->isolate()); | |
244 __ CallStub(&stub); | |
245 } | |
246 __ pop(function); | |
247 __ mov(argument, v0); | |
248 __ Branch(&argument_is_string); | |
249 | |
250 // Load the empty string into a2, remove the receiver from the | |
251 // stack, and jump back to the case where the argument is a string. | |
252 __ bind(&no_arguments); | |
253 __ LoadRoot(argument, Heap::kempty_stringRootIndex); | |
254 __ Drop(1); | |
255 __ Branch(&argument_is_string); | |
256 | |
257 // At this point the argument is already a string. Call runtime to | |
258 // create a string wrapper. | |
259 __ bind(&gc_required); | |
260 __ IncrementCounter(counters->string_ctor_gc_required(), 1, a3, t0); | |
261 { | |
262 FrameScope scope(masm, StackFrame::INTERNAL); | |
263 __ push(argument); | |
264 __ CallRuntime(Runtime::kNewStringWrapper, 1); | |
265 } | |
266 __ Ret(); | |
267 } | 222 } |
268 | 223 |
269 | 224 |
270 static void CallRuntimePassFunction( | 225 static void CallRuntimePassFunction( |
271 MacroAssembler* masm, Runtime::FunctionId function_id) { | 226 MacroAssembler* masm, Runtime::FunctionId function_id) { |
272 FrameScope scope(masm, StackFrame::INTERNAL); | 227 FrameScope scope(masm, StackFrame::INTERNAL); |
273 // Push a copy of the function onto the stack. | 228 // Push a copy of the function onto the stack. |
274 // Push call kind information and function as parameter to the runtime call. | 229 // Push call kind information and function as parameter to the runtime call. |
275 __ Push(a1, a1); | 230 __ Push(a1, a1); |
276 | 231 |
(...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1816 } | 1771 } |
1817 } | 1772 } |
1818 | 1773 |
1819 | 1774 |
1820 #undef __ | 1775 #undef __ |
1821 | 1776 |
1822 } // namespace internal | 1777 } // namespace internal |
1823 } // namespace v8 | 1778 } // namespace v8 |
1824 | 1779 |
1825 #endif // V8_TARGET_ARCH_MIPS | 1780 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |