| 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 __ Push(a1); |
| 181 __ CallStub(&stub); |
| 182 __ Move(a0, v0); |
| 183 __ Pop(a1); |
| 184 } |
| 185 __ bind(&done_convert); |
| 186 } |
| 170 | 187 |
| 171 Register argument = a2; | 188 // 3. Allocate a JSValue wrapper for the string. |
| 172 Label not_cached, argument_is_string; | 189 { |
| 173 __ LookupNumberStringCache(a0, // Input. | 190 // ----------- S t a t e ------------- |
| 174 argument, // Result. | 191 // -- a0 : the first argument |
| 175 a3, // Scratch. | 192 // -- a1 : constructor function |
| 176 a4, // Scratch. | 193 // -- ra : return address |
| 177 a5, // Scratch. | 194 // ----------------------------------- |
| 178 ¬_cached); | |
| 179 __ IncrementCounter(counters->string_ctor_cached_number(), 1, a3, a4); | |
| 180 __ bind(&argument_is_string); | |
| 181 | 195 |
| 182 // ----------- S t a t e ------------- | 196 Label allocate, done_allocate; |
| 183 // -- a2 : argument converted to string | 197 __ Allocate(JSValue::kSize, v0, a2, a3, &allocate, TAG_OBJECT); |
| 184 // -- a1 : constructor function | 198 __ bind(&done_allocate); |
| 185 // -- ra : return address | |
| 186 // ----------------------------------- | |
| 187 | 199 |
| 188 Label gc_required; | 200 // Initialize the JSValue in eax. |
| 189 __ Allocate(JSValue::kSize, | 201 __ LoadGlobalFunctionInitialMap(a1, a2, a3); |
| 190 v0, // Result. | 202 __ sd(a2, FieldMemOperand(v0, HeapObject::kMapOffset)); |
| 191 a3, // Scratch. | 203 __ LoadRoot(a3, Heap::kEmptyFixedArrayRootIndex); |
| 192 a4, // Scratch. | 204 __ sd(a3, FieldMemOperand(v0, JSObject::kPropertiesOffset)); |
| 193 &gc_required, | 205 __ sd(a3, FieldMemOperand(v0, JSObject::kElementsOffset)); |
| 194 TAG_OBJECT); | 206 __ sd(a0, FieldMemOperand(v0, JSValue::kValueOffset)); |
| 207 STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize); |
| 208 __ Ret(); |
| 195 | 209 |
| 196 // Initialising the String Object. | 210 // Fallback to the runtime to allocate in new space. |
| 197 Register map = a3; | 211 __ bind(&allocate); |
| 198 __ LoadGlobalFunctionInitialMap(function, map, a4); | 212 { |
| 199 if (FLAG_debug_code) { | 213 FrameScope scope(masm, StackFrame::INTERNAL); |
| 200 __ lbu(a4, FieldMemOperand(map, Map::kInstanceSizeOffset)); | 214 __ Move(a2, Smi::FromInt(JSValue::kSize)); |
| 201 __ Assert(eq, kUnexpectedStringWrapperInstanceSize, | 215 __ Push(a0, a1, a2); |
| 202 a4, Operand(JSValue::kSize >> kPointerSizeLog2)); | 216 __ CallRuntime(Runtime::kAllocateInNewSpace, 1); |
| 203 __ lbu(a4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset)); | 217 __ Pop(a0, a1); |
| 204 __ Assert(eq, kUnexpectedUnusedPropertiesOfStringWrapper, | 218 } |
| 205 a4, Operand(zero_reg)); | 219 __ jmp(&done_allocate); |
| 206 } | 220 } |
| 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 } | 221 } |
| 267 | 222 |
| 268 | 223 |
| 269 static void CallRuntimePassFunction( | 224 static void CallRuntimePassFunction( |
| 270 MacroAssembler* masm, Runtime::FunctionId function_id) { | 225 MacroAssembler* masm, Runtime::FunctionId function_id) { |
| 271 FrameScope scope(masm, StackFrame::INTERNAL); | 226 FrameScope scope(masm, StackFrame::INTERNAL); |
| 272 // Push a copy of the function onto the stack. | 227 // Push a copy of the function onto the stack. |
| 273 // Push call kind information and function as parameter to the runtime call. | 228 // Push call kind information and function as parameter to the runtime call. |
| 274 __ Push(a1, a1); | 229 __ Push(a1, a1); |
| 275 | 230 |
| (...skipping 1537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1813 } | 1768 } |
| 1814 } | 1769 } |
| 1815 | 1770 |
| 1816 | 1771 |
| 1817 #undef __ | 1772 #undef __ |
| 1818 | 1773 |
| 1819 } // namespace internal | 1774 } // namespace internal |
| 1820 } // namespace v8 | 1775 } // namespace v8 |
| 1821 | 1776 |
| 1822 #endif // V8_TARGET_ARCH_MIPS64 | 1777 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |