OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2989 result_size_ == 1; | 2989 result_size_ == 1; |
2990 } | 2990 } |
2991 | 2991 |
2992 | 2992 |
2993 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { | 2993 void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { |
2994 CEntryStub::GenerateAheadOfTime(isolate); | 2994 CEntryStub::GenerateAheadOfTime(isolate); |
2995 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2995 WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); |
2996 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2996 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); |
2997 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); | 2997 StubFailureTrampolineStub::GenerateAheadOfTime(isolate); |
2998 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); | 2998 RecordWriteStub::GenerateFixedRegStubsAheadOfTime(isolate); |
2999 if (FLAG_optimize_constructed_arrays) { | 2999 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); |
3000 ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate); | |
3001 } | |
3002 } | 3000 } |
3003 | 3001 |
3004 | 3002 |
3005 void CodeStub::GenerateFPStubs(Isolate* isolate) { | 3003 void CodeStub::GenerateFPStubs(Isolate* isolate) { |
3006 SaveFPRegsMode mode = kSaveFPRegs; | 3004 SaveFPRegsMode mode = kSaveFPRegs; |
3007 CEntryStub save_doubles(1, mode); | 3005 CEntryStub save_doubles(1, mode); |
3008 StoreBufferOverflowStub stub(mode); | 3006 StoreBufferOverflowStub stub(mode); |
3009 // These stubs might already be in the snapshot, detect that and don't | 3007 // These stubs might already be in the snapshot, detect that and don't |
3010 // regenerate, which would lead to code stub initialization state being messed | 3008 // regenerate, which would lead to code stub initialization state being messed |
3011 // up. | 3009 // up. |
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4616 | 4614 |
4617 __ bind(&done); | 4615 __ bind(&done); |
4618 __ add(sp, sp, Operand(3 * kPointerSize)); | 4616 __ add(sp, sp, Operand(3 * kPointerSize)); |
4619 __ Ret(); | 4617 __ Ret(); |
4620 | 4618 |
4621 __ bind(&slowcase); | 4619 __ bind(&slowcase); |
4622 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); | 4620 __ TailCallRuntime(Runtime::kRegExpConstructResult, 3, 1); |
4623 } | 4621 } |
4624 | 4622 |
4625 | 4623 |
4626 static void GenerateRecordCallTargetNoArray(MacroAssembler* masm) { | |
4627 // Cache the called function in a global property cell. Cache states | |
4628 // are uninitialized, monomorphic (indicated by a JSFunction), and | |
4629 // megamorphic. | |
4630 // r1 : the function to call | |
4631 // r2 : cache cell for call target | |
4632 Label done; | |
4633 | |
4634 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), | |
4635 masm->isolate()->heap()->undefined_value()); | |
4636 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), | |
4637 masm->isolate()->heap()->the_hole_value()); | |
4638 | |
4639 // Load the cache state into r3. | |
4640 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); | |
4641 | |
4642 // A monomorphic cache hit or an already megamorphic state: invoke the | |
4643 // function without changing the state. | |
4644 __ cmp(r3, r1); | |
4645 __ b(eq, &done); | |
4646 __ CompareRoot(r3, Heap::kUndefinedValueRootIndex); | |
4647 __ b(eq, &done); | |
4648 | |
4649 // A monomorphic miss (i.e, here the cache is not uninitialized) goes | |
4650 // megamorphic. | |
4651 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | |
4652 // MegamorphicSentinel is an immortal immovable object (undefined) so no | |
4653 // write-barrier is needed. | |
4654 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex, ne); | |
4655 __ str(ip, FieldMemOperand(r2, Cell::kValueOffset), ne); | |
4656 | |
4657 // An uninitialized cache is patched with the function. | |
4658 __ str(r1, FieldMemOperand(r2, Cell::kValueOffset), eq); | |
4659 // No need for a write barrier here - cells are rescanned. | |
4660 | |
4661 __ bind(&done); | |
4662 } | |
4663 | |
4664 | |
4665 static void GenerateRecordCallTarget(MacroAssembler* masm) { | 4624 static void GenerateRecordCallTarget(MacroAssembler* masm) { |
4666 // Cache the called function in a global property cell. Cache states | 4625 // Cache the called function in a global property cell. Cache states |
4667 // are uninitialized, monomorphic (indicated by a JSFunction), and | 4626 // are uninitialized, monomorphic (indicated by a JSFunction), and |
4668 // megamorphic. | 4627 // megamorphic. |
4669 // r1 : the function to call | 4628 // r1 : the function to call |
4670 // r2 : cache cell for call target | 4629 // r2 : cache cell for call target |
4671 ASSERT(FLAG_optimize_constructed_arrays); | |
4672 Label initialize, done, miss, megamorphic, not_array_function; | 4630 Label initialize, done, miss, megamorphic, not_array_function; |
4673 | 4631 |
4674 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), | 4632 ASSERT_EQ(*TypeFeedbackCells::MegamorphicSentinel(masm->isolate()), |
4675 masm->isolate()->heap()->undefined_value()); | 4633 masm->isolate()->heap()->undefined_value()); |
4676 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), | 4634 ASSERT_EQ(*TypeFeedbackCells::UninitializedSentinel(masm->isolate()), |
4677 masm->isolate()->heap()->the_hole_value()); | 4635 masm->isolate()->heap()->the_hole_value()); |
4678 | 4636 |
4679 // Load the cache state into r3. | 4637 // Load the cache state into r3. |
4680 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); | 4638 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); |
4681 | 4639 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4765 } | 4723 } |
4766 | 4724 |
4767 // Check that the function is really a JavaScript function. | 4725 // Check that the function is really a JavaScript function. |
4768 // r1: pushed function (to be verified) | 4726 // r1: pushed function (to be verified) |
4769 __ JumpIfSmi(r1, &non_function); | 4727 __ JumpIfSmi(r1, &non_function); |
4770 // Get the map of the function object. | 4728 // Get the map of the function object. |
4771 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 4729 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
4772 __ b(ne, &slow); | 4730 __ b(ne, &slow); |
4773 | 4731 |
4774 if (RecordCallTarget()) { | 4732 if (RecordCallTarget()) { |
4775 if (FLAG_optimize_constructed_arrays) { | 4733 GenerateRecordCallTarget(masm); |
4776 GenerateRecordCallTarget(masm); | |
4777 } else { | |
4778 GenerateRecordCallTargetNoArray(masm); | |
4779 } | |
4780 } | 4734 } |
4781 | 4735 |
4782 // Fast-case: Invoke the function now. | 4736 // Fast-case: Invoke the function now. |
4783 // r1: pushed function | 4737 // r1: pushed function |
4784 ParameterCount actual(argc_); | 4738 ParameterCount actual(argc_); |
4785 | 4739 |
4786 if (ReceiverMightBeImplicit()) { | 4740 if (ReceiverMightBeImplicit()) { |
4787 Label call_as_function; | 4741 Label call_as_function; |
4788 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); | 4742 __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); |
4789 __ b(eq, &call_as_function); | 4743 __ b(eq, &call_as_function); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4844 // r2 : cache cell for call target | 4798 // r2 : cache cell for call target |
4845 Label slow, non_function_call; | 4799 Label slow, non_function_call; |
4846 | 4800 |
4847 // Check that the function is not a smi. | 4801 // Check that the function is not a smi. |
4848 __ JumpIfSmi(r1, &non_function_call); | 4802 __ JumpIfSmi(r1, &non_function_call); |
4849 // Check that the function is a JSFunction. | 4803 // Check that the function is a JSFunction. |
4850 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); | 4804 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); |
4851 __ b(ne, &slow); | 4805 __ b(ne, &slow); |
4852 | 4806 |
4853 if (RecordCallTarget()) { | 4807 if (RecordCallTarget()) { |
4854 if (FLAG_optimize_constructed_arrays) { | 4808 GenerateRecordCallTarget(masm); |
4855 GenerateRecordCallTarget(masm); | |
4856 } else { | |
4857 GenerateRecordCallTargetNoArray(masm); | |
4858 } | |
4859 } | 4809 } |
4860 | 4810 |
4861 // Jump to the function-specific construct stub. | 4811 // Jump to the function-specific construct stub. |
4862 Register jmp_reg = FLAG_optimize_constructed_arrays ? r3 : r2; | 4812 Register jmp_reg = r3; |
4863 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 4813 __ ldr(jmp_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
4864 __ ldr(jmp_reg, FieldMemOperand(jmp_reg, | 4814 __ ldr(jmp_reg, FieldMemOperand(jmp_reg, |
4865 SharedFunctionInfo::kConstructStubOffset)); | 4815 SharedFunctionInfo::kConstructStubOffset)); |
4866 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); | 4816 __ add(pc, jmp_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); |
4867 | 4817 |
4868 // r0: number of arguments | 4818 // r0: number of arguments |
4869 // r1: called object | 4819 // r1: called object |
4870 // r3: object type | 4820 // r3: object type |
4871 Label do_call; | 4821 Label do_call; |
4872 __ bind(&slow); | 4822 __ bind(&slow); |
(...skipping 2461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7334 Label okay_here; | 7284 Label okay_here; |
7335 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); | 7285 Handle<Map> cell_map = masm->isolate()->factory()->cell_map(); |
7336 __ cmp(r2, Operand(undefined_sentinel)); | 7286 __ cmp(r2, Operand(undefined_sentinel)); |
7337 __ b(eq, &okay_here); | 7287 __ b(eq, &okay_here); |
7338 __ ldr(r3, FieldMemOperand(r2, 0)); | 7288 __ ldr(r3, FieldMemOperand(r2, 0)); |
7339 __ cmp(r3, Operand(cell_map)); | 7289 __ cmp(r3, Operand(cell_map)); |
7340 __ Assert(eq, "Expected property cell in register ebx"); | 7290 __ Assert(eq, "Expected property cell in register ebx"); |
7341 __ bind(&okay_here); | 7291 __ bind(&okay_here); |
7342 } | 7292 } |
7343 | 7293 |
7344 if (FLAG_optimize_constructed_arrays) { | 7294 Label no_info, switch_ready; |
7345 Label no_info, switch_ready; | 7295 // Get the elements kind and case on that. |
7346 // Get the elements kind and case on that. | 7296 __ cmp(r2, Operand(undefined_sentinel)); |
7347 __ cmp(r2, Operand(undefined_sentinel)); | 7297 __ b(eq, &no_info); |
7348 __ b(eq, &no_info); | 7298 __ ldr(r3, FieldMemOperand(r2, Cell::kValueOffset)); |
7349 __ ldr(r3, FieldMemOperand(r2, PropertyCell::kValueOffset)); | 7299 __ JumpIfNotSmi(r3, &no_info); |
7350 __ JumpIfNotSmi(r3, &no_info); | 7300 __ SmiUntag(r3); |
7351 __ SmiUntag(r3); | 7301 __ jmp(&switch_ready); |
7352 __ jmp(&switch_ready); | 7302 __ bind(&no_info); |
7353 __ bind(&no_info); | 7303 __ mov(r3, Operand(GetInitialFastElementsKind())); |
7354 __ mov(r3, Operand(GetInitialFastElementsKind())); | 7304 __ bind(&switch_ready); |
7355 __ bind(&switch_ready); | |
7356 | 7305 |
7357 if (argument_count_ == ANY) { | 7306 if (argument_count_ == ANY) { |
7358 Label not_zero_case, not_one_case; | 7307 Label not_zero_case, not_one_case; |
7359 __ tst(r0, r0); | 7308 __ tst(r0, r0); |
7360 __ b(ne, ¬_zero_case); | 7309 __ b(ne, ¬_zero_case); |
7361 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | 7310 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); |
7362 | 7311 |
7363 __ bind(¬_zero_case); | 7312 __ bind(¬_zero_case); |
7364 __ cmp(r0, Operand(1)); | 7313 __ cmp(r0, Operand(1)); |
7365 __ b(gt, ¬_one_case); | 7314 __ b(gt, ¬_one_case); |
7366 CreateArrayDispatchOneArgument(masm); | 7315 CreateArrayDispatchOneArgument(masm); |
7367 | 7316 |
7368 __ bind(¬_one_case); | 7317 __ bind(¬_one_case); |
7369 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | 7318 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); |
7370 } else if (argument_count_ == NONE) { | 7319 } else if (argument_count_ == NONE) { |
7371 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); | 7320 CreateArrayDispatch<ArrayNoArgumentConstructorStub>(masm); |
7372 } else if (argument_count_ == ONE) { | 7321 } else if (argument_count_ == ONE) { |
7373 CreateArrayDispatchOneArgument(masm); | 7322 CreateArrayDispatchOneArgument(masm); |
7374 } else if (argument_count_ == MORE_THAN_ONE) { | 7323 } else if (argument_count_ == MORE_THAN_ONE) { |
7375 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); | 7324 CreateArrayDispatch<ArrayNArgumentsConstructorStub>(masm); |
7376 } else { | |
7377 UNREACHABLE(); | |
7378 } | |
7379 } else { | 7325 } else { |
7380 Label generic_constructor; | 7326 UNREACHABLE(); |
7381 // Run the native code for the Array function called as a constructor. | |
7382 ArrayNativeCode(masm, &generic_constructor); | |
7383 | |
7384 // Jump to the generic construct code in case the specialized code cannot | |
7385 // handle the construction. | |
7386 __ bind(&generic_constructor); | |
7387 Handle<Code> generic_construct_stub = | |
7388 masm->isolate()->builtins()->JSConstructStubGeneric(); | |
7389 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | |
7390 } | 7327 } |
7391 } | 7328 } |
7392 | 7329 |
7393 | 7330 |
7394 void InternalArrayConstructorStub::GenerateCase( | 7331 void InternalArrayConstructorStub::GenerateCase( |
7395 MacroAssembler* masm, ElementsKind kind) { | 7332 MacroAssembler* masm, ElementsKind kind) { |
7396 Label not_zero_case, not_one_case; | 7333 Label not_zero_case, not_one_case; |
7397 Label normal_sequence; | 7334 Label normal_sequence; |
7398 | 7335 |
7399 __ tst(r0, r0); | 7336 __ tst(r0, r0); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7441 | 7378 |
7442 // Initial map for the builtin Array function should be a map. | 7379 // Initial map for the builtin Array function should be a map. |
7443 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 7380 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
7444 // Will both indicate a NULL and a Smi. | 7381 // Will both indicate a NULL and a Smi. |
7445 __ tst(r3, Operand(kSmiTagMask)); | 7382 __ tst(r3, Operand(kSmiTagMask)); |
7446 __ Assert(ne, "Unexpected initial map for Array function"); | 7383 __ Assert(ne, "Unexpected initial map for Array function"); |
7447 __ CompareObjectType(r3, r3, r4, MAP_TYPE); | 7384 __ CompareObjectType(r3, r3, r4, MAP_TYPE); |
7448 __ Assert(eq, "Unexpected initial map for Array function"); | 7385 __ Assert(eq, "Unexpected initial map for Array function"); |
7449 } | 7386 } |
7450 | 7387 |
7451 if (FLAG_optimize_constructed_arrays) { | 7388 // Figure out the right elements kind |
7452 // Figure out the right elements kind | 7389 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
7453 __ ldr(r3, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 7390 // Load the map's "bit field 2" into |result|. We only need the first byte, |
| 7391 // but the following bit field extraction takes care of that anyway. |
| 7392 __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset)); |
| 7393 // Retrieve elements_kind from bit field 2. |
| 7394 __ Ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount); |
7454 | 7395 |
7455 // Load the map's "bit field 2" into |result|. We only need the first byte, | 7396 if (FLAG_debug_code) { |
7456 // but the following bit field extraction takes care of that anyway. | 7397 Label done; |
7457 __ ldr(r3, FieldMemOperand(r3, Map::kBitField2Offset)); | 7398 __ cmp(r3, Operand(FAST_ELEMENTS)); |
7458 // Retrieve elements_kind from bit field 2. | 7399 __ b(eq, &done); |
7459 __ Ubfx(r3, r3, Map::kElementsKindShift, Map::kElementsKindBitCount); | 7400 __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS)); |
| 7401 __ Assert(eq, |
| 7402 "Invalid ElementsKind for InternalArray or InternalPackedArray"); |
| 7403 __ bind(&done); |
| 7404 } |
7460 | 7405 |
7461 if (FLAG_debug_code) { | 7406 Label fast_elements_case; |
7462 Label done; | 7407 __ cmp(r3, Operand(FAST_ELEMENTS)); |
7463 __ cmp(r3, Operand(FAST_ELEMENTS)); | 7408 __ b(eq, &fast_elements_case); |
7464 __ b(eq, &done); | 7409 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
7465 __ cmp(r3, Operand(FAST_HOLEY_ELEMENTS)); | |
7466 __ Assert(eq, | |
7467 "Invalid ElementsKind for InternalArray or InternalPackedArray"); | |
7468 __ bind(&done); | |
7469 } | |
7470 | 7410 |
7471 Label fast_elements_case; | 7411 __ bind(&fast_elements_case); |
7472 __ cmp(r3, Operand(FAST_ELEMENTS)); | 7412 GenerateCase(masm, FAST_ELEMENTS); |
7473 __ b(eq, &fast_elements_case); | |
7474 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | |
7475 | |
7476 __ bind(&fast_elements_case); | |
7477 GenerateCase(masm, FAST_ELEMENTS); | |
7478 } else { | |
7479 Label generic_constructor; | |
7480 // Run the native code for the Array function called as constructor. | |
7481 ArrayNativeCode(masm, &generic_constructor); | |
7482 | |
7483 // Jump to the generic construct code in case the specialized code cannot | |
7484 // handle the construction. | |
7485 __ bind(&generic_constructor); | |
7486 Handle<Code> generic_construct_stub = | |
7487 masm->isolate()->builtins()->JSConstructStubGeneric(); | |
7488 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); | |
7489 } | |
7490 } | 7413 } |
7491 | 7414 |
7492 | 7415 |
7493 #undef __ | 7416 #undef __ |
7494 | 7417 |
7495 } } // namespace v8::internal | 7418 } } // namespace v8::internal |
7496 | 7419 |
7497 #endif // V8_TARGET_ARCH_ARM | 7420 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |