| 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 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 // Load the double value of the parameter into f2, maybe converting the | 161 // Load the double value of the parameter into f2, maybe converting the |
| 162 // parameter to a number first using the ToNumber builtin if necessary. | 162 // parameter to a number first using the ToNumber builtin if necessary. |
| 163 Label convert, convert_smi, convert_number, done_convert; | 163 Label convert, convert_smi, convert_number, done_convert; |
| 164 __ bind(&convert); | 164 __ bind(&convert); |
| 165 __ JumpIfSmi(a2, &convert_smi); | 165 __ JumpIfSmi(a2, &convert_smi); |
| 166 __ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset)); | 166 __ lw(t0, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 167 __ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number); | 167 __ JumpIfRoot(t0, Heap::kHeapNumberMapRootIndex, &convert_number); |
| 168 { | 168 { |
| 169 // Parameter is not a Number, use the ToNumber builtin to convert it. | 169 // Parameter is not a Number, use the ToNumber builtin to convert it. |
| 170 FrameScope scope(masm, StackFrame::MANUAL); | 170 FrameScope scope(masm, StackFrame::MANUAL); |
| 171 __ Push(ra, fp); | |
| 172 __ Move(fp, sp); | |
| 173 __ Push(cp, a1); | |
| 174 __ SmiTag(a0); | 171 __ SmiTag(a0); |
| 175 __ SmiTag(a3); | 172 __ SmiTag(a3); |
| 176 __ Push(a0, t2, a3); | 173 __ EnterBuiltinFrame(cp, a1, a0); |
| 174 __ Push(t2, a3); |
| 177 __ mov(a0, a2); | 175 __ mov(a0, a2); |
| 178 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 176 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
| 179 __ mov(a2, v0); | 177 __ mov(a2, v0); |
| 180 __ Pop(a0, t2, a3); | 178 __ Pop(t2, a3); |
| 179 __ LeaveBuiltinFrame(cp, a1, a0); |
| 180 __ SmiUntag(a3); |
| 181 __ SmiUntag(a0); |
| 181 { | 182 { |
| 182 // Restore the double accumulator value (f0). | 183 // Restore the double accumulator value (f0). |
| 183 Label restore_smi, done_restore; | 184 Label restore_smi, done_restore; |
| 184 __ JumpIfSmi(t2, &restore_smi); | 185 __ JumpIfSmi(t2, &restore_smi); |
| 185 __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset)); | 186 __ ldc1(f0, FieldMemOperand(t2, HeapNumber::kValueOffset)); |
| 186 __ jmp(&done_restore); | 187 __ jmp(&done_restore); |
| 187 __ bind(&restore_smi); | 188 __ bind(&restore_smi); |
| 188 __ SmiToDoubleFPURegister(t2, f0, t0); | 189 __ SmiToDoubleFPURegister(t2, f0, t0); |
| 189 __ bind(&done_restore); | 190 __ bind(&done_restore); |
| 190 } | 191 } |
| 191 __ SmiUntag(a3); | |
| 192 __ SmiUntag(a0); | |
| 193 __ Pop(cp, a1); | |
| 194 __ Pop(ra, fp); | |
| 195 } | 192 } |
| 196 __ jmp(&convert); | 193 __ jmp(&convert); |
| 197 __ bind(&convert_number); | 194 __ bind(&convert_number); |
| 198 __ ldc1(f2, FieldMemOperand(a2, HeapNumber::kValueOffset)); | 195 __ ldc1(f2, FieldMemOperand(a2, HeapNumber::kValueOffset)); |
| 199 __ jmp(&done_convert); | 196 __ jmp(&done_convert); |
| 200 __ bind(&convert_smi); | 197 __ bind(&convert_smi); |
| 201 __ SmiToDoubleFPURegister(a2, f2, t0); | 198 __ SmiToDoubleFPURegister(a2, f2, t0); |
| 202 __ bind(&done_convert); | 199 __ bind(&done_convert); |
| 203 | 200 |
| 204 // Perform the actual comparison with using Min/Max macro instructions the | 201 // Perform the actual comparison with using Min/Max macro instructions the |
| (...skipping 30 matching lines...) Expand all Loading... |
| 235 __ Lsa(sp, sp, a0, kPointerSizeLog2); | 232 __ Lsa(sp, sp, a0, kPointerSizeLog2); |
| 236 __ Ret(USE_DELAY_SLOT); | 233 __ Ret(USE_DELAY_SLOT); |
| 237 __ mov(v0, t2); // In delay slot. | 234 __ mov(v0, t2); // In delay slot. |
| 238 } | 235 } |
| 239 | 236 |
| 240 // static | 237 // static |
| 241 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) { | 238 void Builtins::Generate_NumberConstructor(MacroAssembler* masm) { |
| 242 // ----------- S t a t e ------------- | 239 // ----------- S t a t e ------------- |
| 243 // -- a0 : number of arguments | 240 // -- a0 : number of arguments |
| 244 // -- a1 : constructor function | 241 // -- a1 : constructor function |
| 242 // -- cp : context |
| 245 // -- ra : return address | 243 // -- ra : return address |
| 246 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) | 244 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) |
| 247 // -- sp[argc * 4] : receiver | 245 // -- sp[argc * 4] : receiver |
| 248 // ----------------------------------- | 246 // ----------------------------------- |
| 249 | 247 |
| 250 // 1. Load the first argument into a0 and get rid of the rest (including the | 248 // 1. Load the first argument into a0. |
| 251 // receiver). | |
| 252 Label no_arguments; | 249 Label no_arguments; |
| 253 { | 250 { |
| 254 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); | 251 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); |
| 255 __ Subu(a0, a0, Operand(1)); | 252 __ Subu(t1, a0, Operand(1)); // In delay slot. |
| 256 __ Lsa(sp, sp, a0, kPointerSizeLog2); | 253 __ mov(t0, a0); // Store argc in t0. |
| 257 __ lw(a0, MemOperand(sp)); | 254 __ Lsa(at, sp, t1, kPointerSizeLog2); |
| 258 __ Drop(2); | 255 __ lw(a0, MemOperand(at)); |
| 259 } | 256 } |
| 260 | 257 |
| 261 // 2a. Convert first argument to number. | 258 // 2a. Convert first argument to number. |
| 262 __ Jump(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 259 { |
| 260 FrameScope scope(masm, StackFrame::MANUAL); |
| 261 __ SmiTag(t0); |
| 262 __ EnterBuiltinFrame(cp, a1, t0); |
| 263 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
| 264 __ LeaveBuiltinFrame(cp, a1, t0); |
| 265 __ SmiUntag(t0); |
| 266 } |
| 267 |
| 268 { |
| 269 // Drop all arguments including the receiver. |
| 270 __ Lsa(sp, sp, t0, kPointerSizeLog2); |
| 271 __ DropAndRet(1); |
| 272 } |
| 263 | 273 |
| 264 // 2b. No arguments, return +0. | 274 // 2b. No arguments, return +0. |
| 265 __ bind(&no_arguments); | 275 __ bind(&no_arguments); |
| 266 __ Move(v0, Smi::FromInt(0)); | 276 __ Move(v0, Smi::FromInt(0)); |
| 267 __ DropAndRet(1); | 277 __ DropAndRet(1); |
| 268 } | 278 } |
| 269 | 279 |
| 270 | 280 |
| 271 // static | 281 // static |
| 272 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { | 282 void Builtins::Generate_NumberConstructor_ConstructStub(MacroAssembler* masm) { |
| 273 // ----------- S t a t e ------------- | 283 // ----------- S t a t e ------------- |
| 274 // -- a0 : number of arguments | 284 // -- a0 : number of arguments |
| 275 // -- a1 : constructor function | 285 // -- a1 : constructor function |
| 276 // -- a3 : new target | 286 // -- a3 : new target |
| 287 // -- cp : context |
| 277 // -- ra : return address | 288 // -- ra : return address |
| 278 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) | 289 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) |
| 279 // -- sp[argc * 4] : receiver | 290 // -- sp[argc * 4] : receiver |
| 280 // ----------------------------------- | 291 // ----------------------------------- |
| 281 | 292 |
| 282 // 1. Make sure we operate in the context of the called function. | 293 // 1. Make sure we operate in the context of the called function. |
| 283 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 294 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 284 | 295 |
| 285 // 2. Load the first argument into a0 and get rid of the rest (including the | 296 // 2. Load the first argument into a0. |
| 286 // receiver). | |
| 287 { | 297 { |
| 288 Label no_arguments, done; | 298 Label no_arguments, done; |
| 299 __ mov(t0, a0); // Store argc in t0. |
| 289 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); | 300 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); |
| 290 __ Subu(a0, a0, Operand(1)); | 301 __ Subu(t1, a0, Operand(1)); // In delay slot. |
| 291 __ Lsa(sp, sp, a0, kPointerSizeLog2); | 302 __ Lsa(at, sp, t1, kPointerSizeLog2); |
| 292 __ lw(a0, MemOperand(sp)); | 303 __ lw(a0, MemOperand(at)); |
| 293 __ Drop(2); | |
| 294 __ jmp(&done); | 304 __ jmp(&done); |
| 295 __ bind(&no_arguments); | 305 __ bind(&no_arguments); |
| 296 __ Move(a0, Smi::FromInt(0)); | 306 __ Move(a0, Smi::FromInt(0)); |
| 297 __ Drop(1); | |
| 298 __ bind(&done); | 307 __ bind(&done); |
| 299 } | 308 } |
| 300 | 309 |
| 301 // 3. Make sure a0 is a number. | 310 // 3. Make sure a0 is a number. |
| 302 { | 311 { |
| 303 Label done_convert; | 312 Label done_convert; |
| 304 __ JumpIfSmi(a0, &done_convert); | 313 __ JumpIfSmi(a0, &done_convert); |
| 305 __ GetObjectType(a0, a2, a2); | 314 __ GetObjectType(a0, a2, a2); |
| 306 __ Branch(&done_convert, eq, a2, Operand(HEAP_NUMBER_TYPE)); | 315 __ Branch(&done_convert, eq, a2, Operand(HEAP_NUMBER_TYPE)); |
| 307 { | 316 { |
| 308 FrameScope scope(masm, StackFrame::INTERNAL); | 317 FrameScope scope(masm, StackFrame::MANUAL); |
| 309 __ Push(a1, a3); | 318 __ SmiTag(t0); |
| 319 __ EnterBuiltinFrame(cp, a1, t0); |
| 320 __ Push(a3); |
| 310 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); | 321 __ Call(masm->isolate()->builtins()->ToNumber(), RelocInfo::CODE_TARGET); |
| 311 __ Move(a0, v0); | 322 __ Move(a0, v0); |
| 312 __ Pop(a1, a3); | 323 __ Pop(a3); |
| 324 __ LeaveBuiltinFrame(cp, a1, t0); |
| 325 __ SmiUntag(t0); |
| 313 } | 326 } |
| 314 __ bind(&done_convert); | 327 __ bind(&done_convert); |
| 315 } | 328 } |
| 316 | 329 |
| 317 // 4. Check if new target and constructor differ. | 330 // 4. Check if new target and constructor differ. |
| 318 Label new_object; | 331 Label drop_frame_and_ret, new_object; |
| 319 __ Branch(&new_object, ne, a1, Operand(a3)); | 332 __ Branch(&new_object, ne, a1, Operand(a3)); |
| 320 | 333 |
| 321 // 5. Allocate a JSValue wrapper for the number. | 334 // 5. Allocate a JSValue wrapper for the number. |
| 322 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object); | 335 __ AllocateJSValue(v0, a1, a0, a2, t1, &new_object); |
| 323 __ Ret(); | 336 __ jmp(&drop_frame_and_ret); |
| 324 | 337 |
| 325 // 6. Fallback to the runtime to create new object. | 338 // 6. Fallback to the runtime to create new object. |
| 326 __ bind(&new_object); | 339 __ bind(&new_object); |
| 327 { | 340 { |
| 328 FrameScope scope(masm, StackFrame::INTERNAL); | 341 FrameScope scope(masm, StackFrame::MANUAL); |
| 342 FastNewObjectStub stub(masm->isolate()); |
| 343 __ SmiTag(t0); |
| 344 __ EnterBuiltinFrame(cp, a1, t0); |
| 329 __ Push(a0); // first argument | 345 __ Push(a0); // first argument |
| 330 FastNewObjectStub stub(masm->isolate()); | |
| 331 __ CallStub(&stub); | 346 __ CallStub(&stub); |
| 332 __ Pop(a0); | 347 __ Pop(a0); |
| 348 __ LeaveBuiltinFrame(cp, a1, t0); |
| 349 __ SmiUntag(t0); |
| 333 } | 350 } |
| 334 __ Ret(USE_DELAY_SLOT); | 351 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); |
| 335 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot | 352 |
| 353 __ bind(&drop_frame_and_ret); |
| 354 { |
| 355 __ Lsa(sp, sp, t0, kPointerSizeLog2); |
| 356 __ DropAndRet(1); |
| 357 } |
| 336 } | 358 } |
| 337 | 359 |
| 338 | 360 |
| 339 // static | 361 // static |
| 340 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { | 362 void Builtins::Generate_StringConstructor(MacroAssembler* masm) { |
| 341 // ----------- S t a t e ------------- | 363 // ----------- S t a t e ------------- |
| 342 // -- a0 : number of arguments | 364 // -- a0 : number of arguments |
| 343 // -- a1 : constructor function | 365 // -- a1 : constructor function |
| 366 // -- cp : context |
| 344 // -- ra : return address | 367 // -- ra : return address |
| 345 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) | 368 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) |
| 346 // -- sp[argc * 4] : receiver | 369 // -- sp[argc * 4] : receiver |
| 347 // ----------------------------------- | 370 // ----------------------------------- |
| 348 | 371 |
| 349 // 1. Load the first argument into a0 and get rid of the rest (including the | 372 // 1. Load the first argument into a0. |
| 350 // receiver). | |
| 351 Label no_arguments; | 373 Label no_arguments; |
| 352 { | 374 { |
| 353 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); | 375 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); |
| 354 __ Subu(a0, a0, Operand(1)); | 376 __ Subu(t1, a0, Operand(1)); |
| 355 __ Lsa(sp, sp, a0, kPointerSizeLog2); | 377 __ mov(t0, a0); // Store argc in t0. |
| 356 __ lw(a0, MemOperand(sp)); | 378 __ Lsa(at, sp, t1, kPointerSizeLog2); |
| 357 __ Drop(2); | 379 __ lw(a0, MemOperand(at)); |
| 358 } | 380 } |
| 359 | 381 |
| 360 // 2a. At least one argument, return a0 if it's a string, otherwise | 382 // 2a. At least one argument, return a0 if it's a string, otherwise |
| 361 // dispatch to appropriate conversion. | 383 // dispatch to appropriate conversion. |
| 362 Label to_string, symbol_descriptive_string; | 384 Label drop_frame_and_ret, to_string, symbol_descriptive_string; |
| 363 { | 385 { |
| 364 __ JumpIfSmi(a0, &to_string); | 386 __ JumpIfSmi(a0, &to_string); |
| 365 __ GetObjectType(a0, a1, a1); | 387 __ GetObjectType(a0, t1, t1); |
| 366 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); | 388 STATIC_ASSERT(FIRST_NONSTRING_TYPE == SYMBOL_TYPE); |
| 367 __ Subu(a1, a1, Operand(FIRST_NONSTRING_TYPE)); | 389 __ Subu(t1, t1, Operand(FIRST_NONSTRING_TYPE)); |
| 368 __ Branch(&symbol_descriptive_string, eq, a1, Operand(zero_reg)); | 390 __ Branch(&symbol_descriptive_string, eq, t1, Operand(zero_reg)); |
| 369 __ Branch(&to_string, gt, a1, Operand(zero_reg)); | 391 __ Branch(&to_string, gt, t1, Operand(zero_reg)); |
| 370 __ Ret(USE_DELAY_SLOT); | |
| 371 __ mov(v0, a0); | 392 __ mov(v0, a0); |
| 393 __ jmp(&drop_frame_and_ret); |
| 372 } | 394 } |
| 373 | 395 |
| 374 // 2b. No arguments, return the empty string (and pop the receiver). | 396 // 2b. No arguments, return the empty string (and pop the receiver). |
| 375 __ bind(&no_arguments); | 397 __ bind(&no_arguments); |
| 376 { | 398 { |
| 377 __ LoadRoot(v0, Heap::kempty_stringRootIndex); | 399 __ LoadRoot(v0, Heap::kempty_stringRootIndex); |
| 378 __ DropAndRet(1); | 400 __ DropAndRet(1); |
| 379 } | 401 } |
| 380 | 402 |
| 381 // 3a. Convert a0 to a string. | 403 // 3a. Convert a0 to a string. |
| 382 __ bind(&to_string); | 404 __ bind(&to_string); |
| 383 { | 405 { |
| 406 FrameScope scope(masm, StackFrame::MANUAL); |
| 384 ToStringStub stub(masm->isolate()); | 407 ToStringStub stub(masm->isolate()); |
| 385 __ TailCallStub(&stub); | 408 __ SmiTag(t0); |
| 409 __ EnterBuiltinFrame(cp, a1, t0); |
| 410 __ CallStub(&stub); |
| 411 __ LeaveBuiltinFrame(cp, a1, t0); |
| 412 __ SmiUntag(t0); |
| 386 } | 413 } |
| 414 __ jmp(&drop_frame_and_ret); |
| 387 | 415 |
| 388 // 3b. Convert symbol in a0 to a string. | 416 // 3b. Convert symbol in a0 to a string. |
| 389 __ bind(&symbol_descriptive_string); | 417 __ bind(&symbol_descriptive_string); |
| 390 { | 418 { |
| 419 __ Lsa(sp, sp, t0, kPointerSizeLog2); |
| 420 __ Drop(1); |
| 391 __ Push(a0); | 421 __ Push(a0); |
| 392 __ TailCallRuntime(Runtime::kSymbolDescriptiveString); | 422 __ TailCallRuntime(Runtime::kSymbolDescriptiveString); |
| 393 } | 423 } |
| 424 |
| 425 __ bind(&drop_frame_and_ret); |
| 426 { |
| 427 __ Lsa(sp, sp, t0, kPointerSizeLog2); |
| 428 __ DropAndRet(1); |
| 429 } |
| 394 } | 430 } |
| 395 | 431 |
| 396 | 432 |
| 397 // static | 433 // static |
| 398 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { | 434 void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) { |
| 399 // ----------- S t a t e ------------- | 435 // ----------- S t a t e ------------- |
| 400 // -- a0 : number of arguments | 436 // -- a0 : number of arguments |
| 401 // -- a1 : constructor function | 437 // -- a1 : constructor function |
| 402 // -- a3 : new target | 438 // -- a3 : new target |
| 439 // -- cp : context |
| 403 // -- ra : return address | 440 // -- ra : return address |
| 404 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) | 441 // -- sp[(argc - n - 1) * 4] : arg[n] (zero based) |
| 405 // -- sp[argc * 4] : receiver | 442 // -- sp[argc * 4] : receiver |
| 406 // ----------------------------------- | 443 // ----------------------------------- |
| 407 | 444 |
| 408 // 1. Make sure we operate in the context of the called function. | 445 // 1. Make sure we operate in the context of the called function. |
| 409 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 446 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 410 | 447 |
| 411 // 2. Load the first argument into a0 and get rid of the rest (including the | 448 // 2. Load the first argument into a0. |
| 412 // receiver). | |
| 413 { | 449 { |
| 414 Label no_arguments, done; | 450 Label no_arguments, done; |
| 451 __ mov(t0, a0); // Store argc in t0. |
| 415 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); | 452 __ Branch(USE_DELAY_SLOT, &no_arguments, eq, a0, Operand(zero_reg)); |
| 416 __ Subu(a0, a0, Operand(1)); | 453 __ Subu(t1, a0, Operand(1)); |
| 417 __ Lsa(sp, sp, a0, kPointerSizeLog2); | 454 __ Lsa(at, sp, t1, kPointerSizeLog2); |
| 418 __ lw(a0, MemOperand(sp)); | 455 __ lw(a0, MemOperand(at)); |
| 419 __ Drop(2); | |
| 420 __ jmp(&done); | 456 __ jmp(&done); |
| 421 __ bind(&no_arguments); | 457 __ bind(&no_arguments); |
| 422 __ LoadRoot(a0, Heap::kempty_stringRootIndex); | 458 __ LoadRoot(a0, Heap::kempty_stringRootIndex); |
| 423 __ Drop(1); | |
| 424 __ bind(&done); | 459 __ bind(&done); |
| 425 } | 460 } |
| 426 | 461 |
| 427 // 3. Make sure a0 is a string. | 462 // 3. Make sure a0 is a string. |
| 428 { | 463 { |
| 429 Label convert, done_convert; | 464 Label convert, done_convert; |
| 430 __ JumpIfSmi(a0, &convert); | 465 __ JumpIfSmi(a0, &convert); |
| 431 __ GetObjectType(a0, a2, a2); | 466 __ GetObjectType(a0, a2, a2); |
| 432 __ And(t0, a2, Operand(kIsNotStringMask)); | 467 __ And(t1, a2, Operand(kIsNotStringMask)); |
| 433 __ Branch(&done_convert, eq, t0, Operand(zero_reg)); | 468 __ Branch(&done_convert, eq, t1, Operand(zero_reg)); |
| 434 __ bind(&convert); | 469 __ bind(&convert); |
| 435 { | 470 { |
| 436 FrameScope scope(masm, StackFrame::INTERNAL); | 471 FrameScope scope(masm, StackFrame::MANUAL); |
| 437 ToStringStub stub(masm->isolate()); | 472 ToStringStub stub(masm->isolate()); |
| 438 __ Push(a1, a3); | 473 __ SmiTag(t0); |
| 474 __ EnterBuiltinFrame(cp, a1, t0); |
| 475 __ Push(a3); |
| 439 __ CallStub(&stub); | 476 __ CallStub(&stub); |
| 440 __ Move(a0, v0); | 477 __ Move(a0, v0); |
| 441 __ Pop(a1, a3); | 478 __ Pop(a3); |
| 479 __ LeaveBuiltinFrame(cp, a1, t0); |
| 480 __ SmiUntag(t0); |
| 442 } | 481 } |
| 443 __ bind(&done_convert); | 482 __ bind(&done_convert); |
| 444 } | 483 } |
| 445 | 484 |
| 446 // 4. Check if new target and constructor differ. | 485 // 4. Check if new target and constructor differ. |
| 447 Label new_object; | 486 Label drop_frame_and_ret, new_object; |
| 448 __ Branch(&new_object, ne, a1, Operand(a3)); | 487 __ Branch(&new_object, ne, a1, Operand(a3)); |
| 449 | 488 |
| 450 // 5. Allocate a JSValue wrapper for the string. | 489 // 5. Allocate a JSValue wrapper for the string. |
| 451 __ AllocateJSValue(v0, a1, a0, a2, t0, &new_object); | 490 __ AllocateJSValue(v0, a1, a0, a2, t1, &new_object); |
| 452 __ Ret(); | 491 __ jmp(&drop_frame_and_ret); |
| 453 | 492 |
| 454 // 6. Fallback to the runtime to create new object. | 493 // 6. Fallback to the runtime to create new object. |
| 455 __ bind(&new_object); | 494 __ bind(&new_object); |
| 456 { | 495 { |
| 457 FrameScope scope(masm, StackFrame::INTERNAL); | 496 FrameScope scope(masm, StackFrame::MANUAL); |
| 497 FastNewObjectStub stub(masm->isolate()); |
| 498 __ SmiTag(t0); |
| 499 __ EnterBuiltinFrame(cp, a1, t0); |
| 458 __ Push(a0); // first argument | 500 __ Push(a0); // first argument |
| 459 FastNewObjectStub stub(masm->isolate()); | |
| 460 __ CallStub(&stub); | 501 __ CallStub(&stub); |
| 461 __ Pop(a0); | 502 __ Pop(a0); |
| 503 __ LeaveBuiltinFrame(cp, a1, t0); |
| 504 __ SmiUntag(t0); |
| 462 } | 505 } |
| 463 __ Ret(USE_DELAY_SLOT); | 506 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); |
| 464 __ sw(a0, FieldMemOperand(v0, JSValue::kValueOffset)); // In delay slot | 507 |
| 508 __ bind(&drop_frame_and_ret); |
| 509 { |
| 510 __ Lsa(sp, sp, t0, kPointerSizeLog2); |
| 511 __ DropAndRet(1); |
| 512 } |
| 465 } | 513 } |
| 466 | 514 |
| 467 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { | 515 static void GenerateTailCallToSharedCode(MacroAssembler* masm) { |
| 468 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | 516 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 469 __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset)); | 517 __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset)); |
| 470 __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag)); | 518 __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 471 __ Jump(at); | 519 __ Jump(at); |
| 472 } | 520 } |
| 473 | 521 |
| 474 static void GenerateTailCallToReturnedCode(MacroAssembler* masm, | 522 static void GenerateTailCallToReturnedCode(MacroAssembler* masm, |
| (...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1794 __ li(a1, Operand(Smi::FromInt(field_index))); | 1842 __ li(a1, Operand(Smi::FromInt(field_index))); |
| 1795 __ CallCFunction( | 1843 __ CallCFunction( |
| 1796 ExternalReference::get_date_field_function(masm->isolate()), 2); | 1844 ExternalReference::get_date_field_function(masm->isolate()), 2); |
| 1797 } | 1845 } |
| 1798 __ Ret(); | 1846 __ Ret(); |
| 1799 | 1847 |
| 1800 // 3. Raise a TypeError if the receiver is not a date. | 1848 // 3. Raise a TypeError if the receiver is not a date. |
| 1801 __ bind(&receiver_not_date); | 1849 __ bind(&receiver_not_date); |
| 1802 { | 1850 { |
| 1803 FrameScope scope(masm, StackFrame::MANUAL); | 1851 FrameScope scope(masm, StackFrame::MANUAL); |
| 1804 __ Push(a0, ra, fp); | 1852 __ Push(a0); |
| 1805 __ Move(fp, sp); | 1853 __ Move(a0, Smi::FromInt(0)); |
| 1806 __ Push(cp, a1); | 1854 __ EnterBuiltinFrame(cp, a1, a0); |
| 1807 __ Push(Smi::FromInt(0)); | |
| 1808 __ CallRuntime(Runtime::kThrowNotDateError); | 1855 __ CallRuntime(Runtime::kThrowNotDateError); |
| 1809 } | 1856 } |
| 1810 } | 1857 } |
| 1811 | 1858 |
| 1812 // static | 1859 // static |
| 1813 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { | 1860 void Builtins::Generate_FunctionPrototypeApply(MacroAssembler* masm) { |
| 1814 // ----------- S t a t e ------------- | 1861 // ----------- S t a t e ------------- |
| 1815 // -- a0 : argc | 1862 // -- a0 : argc |
| 1816 // -- sp[0] : argArray | 1863 // -- sp[0] : argArray |
| 1817 // -- sp[4] : thisArg | 1864 // -- sp[4] : thisArg |
| (...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3012 } | 3059 } |
| 3013 } | 3060 } |
| 3014 | 3061 |
| 3015 | 3062 |
| 3016 #undef __ | 3063 #undef __ |
| 3017 | 3064 |
| 3018 } // namespace internal | 3065 } // namespace internal |
| 3019 } // namespace v8 | 3066 } // namespace v8 |
| 3020 | 3067 |
| 3021 #endif // V8_TARGET_ARCH_MIPS | 3068 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |