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