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 2306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2317 __ j(equal, &done, Label::kNear); | 2317 __ j(equal, &done, Label::kNear); |
2318 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), | 2318 __ CompareRoot(FieldOperand(result, HeapObject::kMapOffset), |
2319 Heap::kFixedCOWArrayMapRootIndex); | 2319 Heap::kFixedCOWArrayMapRootIndex); |
2320 __ j(equal, &done, Label::kNear); | 2320 __ j(equal, &done, Label::kNear); |
2321 Register temp((result.is(rax)) ? rbx : rax); | 2321 Register temp((result.is(rax)) ? rbx : rax); |
2322 __ push(temp); | 2322 __ push(temp); |
2323 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); | 2323 __ movq(temp, FieldOperand(result, HeapObject::kMapOffset)); |
2324 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); | 2324 __ movzxbq(temp, FieldOperand(temp, Map::kBitField2Offset)); |
2325 __ and_(temp, Immediate(Map::kElementsKindMask)); | 2325 __ and_(temp, Immediate(Map::kElementsKindMask)); |
2326 __ shr(temp, Immediate(Map::kElementsKindShift)); | 2326 __ shr(temp, Immediate(Map::kElementsKindShift)); |
2327 __ cmpl(temp, Immediate(FAST_ELEMENTS)); | 2327 __ cmpl(temp, Immediate(GetInitialFastElementsKind())); |
2328 __ j(equal, &ok, Label::kNear); | 2328 __ j(less, &fail, Label::kNear); |
| 2329 __ cmpl(temp, Immediate(TERMINAL_FAST_ELEMENTS_KIND)); |
| 2330 __ j(less_equal, &ok, Label::kNear); |
2329 __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); | 2331 __ cmpl(temp, Immediate(FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND)); |
2330 __ j(less, &fail, Label::kNear); | 2332 __ j(less, &fail, Label::kNear); |
2331 __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); | 2333 __ cmpl(temp, Immediate(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND)); |
2332 __ j(less_equal, &ok, Label::kNear); | 2334 __ j(less_equal, &ok, Label::kNear); |
2333 __ bind(&fail); | 2335 __ bind(&fail); |
2334 __ Abort("Check for fast or external elements failed"); | 2336 __ Abort("Check for fast or external elements failed"); |
2335 __ bind(&ok); | 2337 __ bind(&ok); |
2336 __ pop(temp); | 2338 __ pop(temp); |
2337 __ bind(&done); | 2339 __ bind(&done); |
2338 } | 2340 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2396 LLoadKeyedFastDoubleElement* instr) { | 2398 LLoadKeyedFastDoubleElement* instr) { |
2397 XMMRegister result(ToDoubleRegister(instr->result())); | 2399 XMMRegister result(ToDoubleRegister(instr->result())); |
2398 | 2400 |
2399 if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) { | 2401 if (instr->hydrogen()->IsDehoisted() && !instr->key()->IsConstantOperand()) { |
2400 // Sign extend key because it could be a 32 bit negative value | 2402 // Sign extend key because it could be a 32 bit negative value |
2401 // and the dehoisted address computation happens in 64 bits | 2403 // and the dehoisted address computation happens in 64 bits |
2402 Register key_reg = ToRegister(instr->key()); | 2404 Register key_reg = ToRegister(instr->key()); |
2403 __ movsxlq(key_reg, key_reg); | 2405 __ movsxlq(key_reg, key_reg); |
2404 } | 2406 } |
2405 | 2407 |
2406 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + | 2408 if (instr->hydrogen()->RequiresHoleCheck()) { |
2407 sizeof(kHoleNanLower32); | 2409 int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag + |
2408 Operand hole_check_operand = BuildFastArrayOperand( | 2410 sizeof(kHoleNanLower32); |
2409 instr->elements(), | 2411 Operand hole_check_operand = BuildFastArrayOperand( |
2410 instr->key(), | 2412 instr->elements(), |
2411 FAST_DOUBLE_ELEMENTS, | 2413 instr->key(), |
2412 offset, | 2414 FAST_DOUBLE_ELEMENTS, |
2413 instr->additional_index()); | 2415 offset, |
2414 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 2416 instr->additional_index()); |
2415 DeoptimizeIf(equal, instr->environment()); | 2417 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
| 2418 DeoptimizeIf(equal, instr->environment()); |
| 2419 } |
2416 | 2420 |
2417 Operand double_load_operand = BuildFastArrayOperand( | 2421 Operand double_load_operand = BuildFastArrayOperand( |
2418 instr->elements(), | 2422 instr->elements(), |
2419 instr->key(), | 2423 instr->key(), |
2420 FAST_DOUBLE_ELEMENTS, | 2424 FAST_DOUBLE_ELEMENTS, |
2421 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 2425 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
2422 instr->additional_index()); | 2426 instr->additional_index()); |
2423 __ movsd(result, double_load_operand); | 2427 __ movsd(result, double_load_operand); |
2424 } | 2428 } |
2425 | 2429 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2494 __ movl(result, operand); | 2498 __ movl(result, operand); |
2495 __ testl(result, result); | 2499 __ testl(result, result); |
2496 // TODO(danno): we could be more clever here, perhaps having a special | 2500 // TODO(danno): we could be more clever here, perhaps having a special |
2497 // version of the stub that detects if the overflow case actually | 2501 // version of the stub that detects if the overflow case actually |
2498 // happens, and generate code that returns a double rather than int. | 2502 // happens, and generate code that returns a double rather than int. |
2499 DeoptimizeIf(negative, instr->environment()); | 2503 DeoptimizeIf(negative, instr->environment()); |
2500 break; | 2504 break; |
2501 case EXTERNAL_FLOAT_ELEMENTS: | 2505 case EXTERNAL_FLOAT_ELEMENTS: |
2502 case EXTERNAL_DOUBLE_ELEMENTS: | 2506 case EXTERNAL_DOUBLE_ELEMENTS: |
2503 case FAST_ELEMENTS: | 2507 case FAST_ELEMENTS: |
2504 case FAST_SMI_ONLY_ELEMENTS: | 2508 case FAST_SMI_ELEMENTS: |
2505 case FAST_DOUBLE_ELEMENTS: | 2509 case FAST_DOUBLE_ELEMENTS: |
| 2510 case FAST_HOLEY_ELEMENTS: |
| 2511 case FAST_HOLEY_SMI_ELEMENTS: |
| 2512 case FAST_HOLEY_DOUBLE_ELEMENTS: |
2506 case DICTIONARY_ELEMENTS: | 2513 case DICTIONARY_ELEMENTS: |
2507 case NON_STRICT_ARGUMENTS_ELEMENTS: | 2514 case NON_STRICT_ARGUMENTS_ELEMENTS: |
2508 UNREACHABLE(); | 2515 UNREACHABLE(); |
2509 break; | 2516 break; |
2510 } | 2517 } |
2511 } | 2518 } |
2512 } | 2519 } |
2513 | 2520 |
2514 | 2521 |
2515 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2522 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3396 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3403 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3397 __ movw(operand, value); | 3404 __ movw(operand, value); |
3398 break; | 3405 break; |
3399 case EXTERNAL_INT_ELEMENTS: | 3406 case EXTERNAL_INT_ELEMENTS: |
3400 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3407 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3401 __ movl(operand, value); | 3408 __ movl(operand, value); |
3402 break; | 3409 break; |
3403 case EXTERNAL_FLOAT_ELEMENTS: | 3410 case EXTERNAL_FLOAT_ELEMENTS: |
3404 case EXTERNAL_DOUBLE_ELEMENTS: | 3411 case EXTERNAL_DOUBLE_ELEMENTS: |
3405 case FAST_ELEMENTS: | 3412 case FAST_ELEMENTS: |
3406 case FAST_SMI_ONLY_ELEMENTS: | 3413 case FAST_SMI_ELEMENTS: |
3407 case FAST_DOUBLE_ELEMENTS: | 3414 case FAST_DOUBLE_ELEMENTS: |
| 3415 case FAST_HOLEY_ELEMENTS: |
| 3416 case FAST_HOLEY_SMI_ELEMENTS: |
| 3417 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3408 case DICTIONARY_ELEMENTS: | 3418 case DICTIONARY_ELEMENTS: |
3409 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3419 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3410 UNREACHABLE(); | 3420 UNREACHABLE(); |
3411 break; | 3421 break; |
3412 } | 3422 } |
3413 } | 3423 } |
3414 } | 3424 } |
3415 | 3425 |
3416 | 3426 |
3417 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 3427 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3532 | 3542 |
3533 Handle<Map> from_map = instr->original_map(); | 3543 Handle<Map> from_map = instr->original_map(); |
3534 Handle<Map> to_map = instr->transitioned_map(); | 3544 Handle<Map> to_map = instr->transitioned_map(); |
3535 ElementsKind from_kind = from_map->elements_kind(); | 3545 ElementsKind from_kind = from_map->elements_kind(); |
3536 ElementsKind to_kind = to_map->elements_kind(); | 3546 ElementsKind to_kind = to_map->elements_kind(); |
3537 | 3547 |
3538 Label not_applicable; | 3548 Label not_applicable; |
3539 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); | 3549 __ Cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); |
3540 __ j(not_equal, ¬_applicable); | 3550 __ j(not_equal, ¬_applicable); |
3541 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 3551 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
3542 if (from_kind == FAST_SMI_ONLY_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3552 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
3543 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 3553 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
3544 // Write barrier. | 3554 // Write barrier. |
3545 ASSERT_NE(instr->temp_reg(), NULL); | 3555 ASSERT_NE(instr->temp_reg(), NULL); |
3546 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 3556 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
3547 ToRegister(instr->temp_reg()), kDontSaveFPRegs); | 3557 ToRegister(instr->temp_reg()), kDontSaveFPRegs); |
3548 } else if (from_kind == FAST_SMI_ONLY_ELEMENTS && | 3558 } else if (IsFastSmiElementsKind(from_kind) && |
3549 to_kind == FAST_DOUBLE_ELEMENTS) { | 3559 IsFastDoubleElementsKind(to_kind)) { |
3550 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3560 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3551 ASSERT(fixed_object_reg.is(rdx)); | 3561 ASSERT(fixed_object_reg.is(rdx)); |
3552 ASSERT(new_map_reg.is(rbx)); | 3562 ASSERT(new_map_reg.is(rbx)); |
3553 __ movq(fixed_object_reg, object_reg); | 3563 __ movq(fixed_object_reg, object_reg); |
3554 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), | 3564 CallCode(isolate()->builtins()->TransitionElementsSmiToDouble(), |
3555 RelocInfo::CODE_TARGET, instr); | 3565 RelocInfo::CODE_TARGET, instr); |
3556 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { | 3566 } else if (IsFastDoubleElementsKind(from_kind) && |
| 3567 IsFastObjectElementsKind(to_kind)) { |
3557 Register fixed_object_reg = ToRegister(instr->temp_reg()); | 3568 Register fixed_object_reg = ToRegister(instr->temp_reg()); |
3558 ASSERT(fixed_object_reg.is(rdx)); | 3569 ASSERT(fixed_object_reg.is(rdx)); |
3559 ASSERT(new_map_reg.is(rbx)); | 3570 ASSERT(new_map_reg.is(rbx)); |
3560 __ movq(fixed_object_reg, object_reg); | 3571 __ movq(fixed_object_reg, object_reg); |
3561 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), | 3572 CallCode(isolate()->builtins()->TransitionElementsDoubleToObject(), |
3562 RelocInfo::CODE_TARGET, instr); | 3573 RelocInfo::CODE_TARGET, instr); |
3563 } else { | 3574 } else { |
3564 UNREACHABLE(); | 3575 UNREACHABLE(); |
3565 } | 3576 } |
3566 __ bind(¬_applicable); | 3577 __ bind(¬_applicable); |
(...skipping 653 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4220 } | 4231 } |
4221 | 4232 |
4222 | 4233 |
4223 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4234 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
4224 Heap* heap = isolate()->heap(); | 4235 Heap* heap = isolate()->heap(); |
4225 ElementsKind boilerplate_elements_kind = | 4236 ElementsKind boilerplate_elements_kind = |
4226 instr->hydrogen()->boilerplate_elements_kind(); | 4237 instr->hydrogen()->boilerplate_elements_kind(); |
4227 | 4238 |
4228 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4239 // Deopt if the array literal boilerplate ElementsKind is of a type different |
4229 // than the expected one. The check isn't necessary if the boilerplate has | 4240 // than the expected one. The check isn't necessary if the boilerplate has |
4230 // already been converted to FAST_ELEMENTS. | 4241 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
4231 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4242 if (CanTransitionToMoreGeneralFastElementsKind( |
| 4243 boilerplate_elements_kind, true)) { |
4232 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); | 4244 __ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object()); |
4233 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 4245 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
4234 // Load the map's "bit field 2". | 4246 // Load the map's "bit field 2". |
4235 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); | 4247 __ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset)); |
4236 // Retrieve elements_kind from bit field 2. | 4248 // Retrieve elements_kind from bit field 2. |
4237 __ and_(rbx, Immediate(Map::kElementsKindMask)); | 4249 __ and_(rbx, Immediate(Map::kElementsKindMask)); |
4238 __ cmpb(rbx, Immediate(boilerplate_elements_kind << | 4250 __ cmpb(rbx, Immediate(boilerplate_elements_kind << |
4239 Map::kElementsKindShift)); | 4251 Map::kElementsKindShift)); |
4240 DeoptimizeIf(not_equal, instr->environment()); | 4252 DeoptimizeIf(not_equal, instr->environment()); |
4241 } | 4253 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4367 } | 4379 } |
4368 } | 4380 } |
4369 } | 4381 } |
4370 | 4382 |
4371 | 4383 |
4372 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { | 4384 void LCodeGen::DoFastLiteral(LFastLiteral* instr) { |
4373 int size = instr->hydrogen()->total_size(); | 4385 int size = instr->hydrogen()->total_size(); |
4374 ElementsKind boilerplate_elements_kind = | 4386 ElementsKind boilerplate_elements_kind = |
4375 instr->hydrogen()->boilerplate()->GetElementsKind(); | 4387 instr->hydrogen()->boilerplate()->GetElementsKind(); |
4376 | 4388 |
4377 // Deopt if the literal boilerplate ElementsKind is of a type different than | 4389 // Deopt if the array literal boilerplate ElementsKind is of a type different |
4378 // the expected one. The check isn't necessary if the boilerplate has already | 4390 // than the expected one. The check isn't necessary if the boilerplate has |
4379 // been converted to FAST_ELEMENTS. | 4391 // already been converted to TERMINAL_FAST_ELEMENTS_KIND. |
4380 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4392 if (CanTransitionToMoreGeneralFastElementsKind( |
| 4393 boilerplate_elements_kind, true)) { |
4381 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); | 4394 __ LoadHeapObject(rbx, instr->hydrogen()->boilerplate()); |
4382 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); | 4395 __ movq(rcx, FieldOperand(rbx, HeapObject::kMapOffset)); |
4383 // Load the map's "bit field 2". | 4396 // Load the map's "bit field 2". |
4384 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); | 4397 __ movb(rcx, FieldOperand(rcx, Map::kBitField2Offset)); |
4385 // Retrieve elements_kind from bit field 2. | 4398 // Retrieve elements_kind from bit field 2. |
4386 __ and_(rcx, Immediate(Map::kElementsKindMask)); | 4399 __ and_(rcx, Immediate(Map::kElementsKindMask)); |
4387 __ cmpb(rcx, Immediate(boilerplate_elements_kind << | 4400 __ cmpb(rcx, Immediate(boilerplate_elements_kind << |
4388 Map::kElementsKindShift)); | 4401 Map::kElementsKindShift)); |
4389 DeoptimizeIf(not_equal, instr->environment()); | 4402 DeoptimizeIf(not_equal, instr->environment()); |
4390 } | 4403 } |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4866 FixedArray::kHeaderSize - kPointerSize)); | 4879 FixedArray::kHeaderSize - kPointerSize)); |
4867 __ bind(&done); | 4880 __ bind(&done); |
4868 } | 4881 } |
4869 | 4882 |
4870 | 4883 |
4871 #undef __ | 4884 #undef __ |
4872 | 4885 |
4873 } } // namespace v8::internal | 4886 } } // namespace v8::internal |
4874 | 4887 |
4875 #endif // V8_TARGET_ARCH_X64 | 4888 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |