| 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 |