Version 3.31.1 (based on 18cf6c9ac96a62ec320fc10d738d26fba784e2f4) Fix has_constant_parameter_count() confusion in LReturn (Chromium issue 431602). Performance and stability improvements on all platforms. git-svn-id: https://v8.googlecode.com/svn/trunk@25275 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/BUILD.gn b/BUILD.gn index 1758ee9..d77931c 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -572,6 +572,8 @@ "src/compiler/raw-machine-assembler.h", "src/compiler/register-allocator.cc", "src/compiler/register-allocator.h", + "src/compiler/register-allocator-verifier.cc", + "src/compiler/register-allocator-verifier.h", "src/compiler/register-configuration.cc", "src/compiler/register-configuration.h", "src/compiler/representation-change.h",
diff --git a/ChangeLog b/ChangeLog index 1e29853..c75f146 100644 --- a/ChangeLog +++ b/ChangeLog
@@ -1,3 +1,11 @@ +2014-11-12: Version 3.31.1 + + Fix has_constant_parameter_count() confusion in LReturn (Chromium issue + 431602). + + Performance and stability improvements on all platforms. + + 2014-11-05: Version 3.30.33 `1..isPrototypeOf.call(null)` should return false, not throw TypeError
diff --git a/build/standalone.gypi b/build/standalone.gypi index 47b2763..6cc0599 100644 --- a/build/standalone.gypi +++ b/build/standalone.gypi
@@ -127,6 +127,16 @@ 'arm_fpu%': 'vfpv3', 'arm_float_abi%': 'default', 'arm_thumb': 'default', + + # Default MIPS variable settings. + 'mips_arch_variant%': 'r2', + # Possible values fp32, fp64, fpxx. + # fp32 - 32 32-bit FPU registers are available, doubles are placed in + # register pairs. + # fp64 - 32 64-bit FPU registers are available. + # fpxx - compatibility mode, it chooses fp32 or fp64 depending on runtime + # detection + 'mips_fpu_mode%': 'fp32', }, 'target_defaults': { 'variables': {
diff --git a/build/toolchain.gypi b/build/toolchain.gypi index 82a10e8..df2f988 100644 --- a/build/toolchain.gypi +++ b/build/toolchain.gypi
@@ -55,17 +55,6 @@ # Similar to the ARM hard float ABI but on MIPS. 'v8_use_mips_abi_hardfloat%': 'true', - # Default arch variant for MIPS. - 'mips_arch_variant%': 'r2', - - # Possible values fp32, fp64, fpxx. - # fp32 - 32 32-bit FPU registers are available, doubles are placed in - # register pairs. - # fp64 - 32 64-bit FPU registers are available. - # fpxx - compatibility mode, it chooses fp32 or fp64 depending on runtime - # detection - 'mips_fpu_mode%': 'fp32', - 'v8_enable_backtrace%': 0, # Enable profiling support. Only required on Windows. @@ -278,10 +267,27 @@ 'V8_TARGET_ARCH_MIPS', ], 'conditions': [ - ['v8_target_arch==target_arch and android_webview_build==0', { - # Target built with a Mips CXX compiler. - 'target_conditions': [ - ['_toolset=="target"', { + [ 'v8_can_use_fpu_instructions=="true"', { + 'defines': [ + 'CAN_USE_FPU_INSTRUCTIONS', + ], + }], + [ 'v8_use_mips_abi_hardfloat=="true"', { + 'defines': [ + '__mips_hard_float=1', + 'CAN_USE_FPU_INSTRUCTIONS', + ], + }, { + 'defines': [ + '__mips_soft_float=1' + ] + }], + ], + 'target_conditions': [ + ['_toolset=="target"', { + 'conditions': [ + ['v8_target_arch==target_arch and android_webview_build==0', { + # Target built with a Mips CXX compiler. 'cflags': ['-EB'], 'ldflags': ['-EB'], 'conditions': [ @@ -292,16 +298,11 @@ 'cflags': ['-msoft-float'], 'ldflags': ['-msoft-float'], }], - ['mips_fpu_mode=="fp64"', { - 'cflags': ['-mfp64'], - }], - ['mips_fpu_mode=="fpxx"', { - 'cflags': ['-mfpxx'], - }], - ['mips_fpu_mode=="fp32"', { - 'cflags': ['-mfp32'], - }], ['mips_arch_variant=="r6"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R6', + 'FPU_MODE_FP64', + ], 'cflags!': ['-mfp32', '-mfpxx'], 'cflags': ['-mips32r6', '-Wa,-mips32r6'], 'ldflags': [ @@ -311,23 +312,145 @@ ], }], ['mips_arch_variant=="r2"', { + 'conditions': [ + [ 'mips_fpu_mode=="fp64"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP64', + ], + 'cflags': ['-mfp64'], + }], + ['mips_fpu_mode=="fpxx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FPXX', + ], + 'cflags': ['-mfpxx'], + }], + ['mips_fpu_mode=="fp32"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP32', + ], + 'cflags': ['-mfp32'], + }], + ], 'cflags': ['-mips32r2', '-Wa,-mips32r2'], 'ldflags': ['-mips32r2'], }], ['mips_arch_variant=="r1"', { + 'defines': [ + 'FPU_MODE_FP32', + ], 'cflags!': ['-mfp64', '-mfpxx'], 'cflags': ['-mips32', '-Wa,-mips32'], 'ldflags': ['-mips32'], }], ['mips_arch_variant=="rx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32RX', + 'FPU_MODE_FPXX', + ], 'cflags!': ['-mfp64', '-mfp32'], 'cflags': ['-mips32', '-Wa,-mips32', '-mfpxx'], 'ldflags': ['-mips32'], }], ], + }, { + # 'v8_target_arch!=target_arch' + # Target not built with an MIPS CXX compiler (simulator build). + 'conditions': [ + ['mips_arch_variant=="r6"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R6', + 'FPU_MODE_FP64', + ], + }], + ['mips_arch_variant=="r2"', { + 'conditions': [ + [ 'mips_fpu_mode=="fp64"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP64', + ], + }], + ['mips_fpu_mode=="fpxx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FPXX', + ], + }], + ['mips_fpu_mode=="fp32"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP32', + ], + }], + ], + }], + ['mips_arch_variant=="r1"', { + 'defines': [ + 'FPU_MODE_FP32', + ], + }], + ['mips_arch_variant=="rx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32RX', + 'FPU_MODE_FPXX', + ], + }], + ], }], ], - }], + }], #_toolset=="target" + ['_toolset=="host"', { + 'conditions': [ + ['mips_arch_variant=="rx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32RX', + 'FPU_MODE_FPXX', + ], + }], + ['mips_arch_variant=="r6"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R6', + 'FPU_MODE_FP64', + ], + }], + ['mips_arch_variant=="r2"', { + 'conditions': [ + ['mips_fpu_mode=="fp64"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP64', + ], + }], + ['mips_fpu_mode=="fpxx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FPXX', + ], + }], + ['mips_fpu_mode=="fp32"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP32' + ], + }], + ], + }], + ['mips_arch_variant=="r1"', { + 'defines': ['FPU_MODE_FP32',], + }], + ] + }], #_toolset=="host" + ], + }], # v8_target_arch=="mips" + ['v8_target_arch=="mipsel"', { + 'defines': [ + 'V8_TARGET_ARCH_MIPS', + ], + 'conditions': [ [ 'v8_can_use_fpu_instructions=="true"', { 'defines': [ 'CAN_USE_FPU_INSTRUCTIONS', @@ -343,46 +466,12 @@ '__mips_soft_float=1' ], }], - ['mips_arch_variant=="rx"', { - 'defines': [ - '_MIPS_ARCH_MIPS32RX', - 'FPU_MODE_FPXX', - ], - }], - ['mips_arch_variant=="r6"', { - 'defines': [ - '_MIPS_ARCH_MIPS32R6', - 'FPU_MODE_FP64', - ], - }], - ['mips_arch_variant=="r2"', { - 'defines': ['_MIPS_ARCH_MIPS32R2',], + ], + 'target_conditions': [ + ['_toolset=="target"', { 'conditions': [ - ['mips_fpu_mode=="fp64"', { - 'defines': ['FPU_MODE_FP64',], - }], - ['mips_fpu_mode=="fpxx"', { - 'defines': ['FPU_MODE_FPXX',], - }], - ['mips_fpu_mode=="fp32"', { - 'defines': ['FPU_MODE_FP32',], - }], - ], - }], - ['mips_arch_variant=="r1"', { - 'defines': ['FPU_MODE_FP32',], - }], - ], - }], # v8_target_arch=="mips" - ['v8_target_arch=="mipsel"', { - 'defines': [ - 'V8_TARGET_ARCH_MIPS', - ], - 'conditions': [ - ['v8_target_arch==target_arch and android_webview_build==0', { - # Target built with a Mips CXX compiler. - 'target_conditions': [ - ['_toolset=="target"', { + ['v8_target_arch==target_arch and android_webview_build==0', { + # Target built with a Mips CXX compiler. 'cflags': ['-EL'], 'ldflags': ['-EL'], 'conditions': [ @@ -393,16 +482,11 @@ 'cflags': ['-msoft-float'], 'ldflags': ['-msoft-float'], }], - ['mips_fpu_mode=="fp64"', { - 'cflags': ['-mfp64'], - }], - ['mips_fpu_mode=="fpxx"', { - 'cflags': ['-mfpxx'], - }], - ['mips_fpu_mode=="fp32"', { - 'cflags': ['-mfp32'], - }], ['mips_arch_variant=="r6"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R6', + 'FPU_MODE_FP64', + ], 'cflags!': ['-mfp32', '-mfpxx'], 'cflags': ['-mips32r6', '-Wa,-mips32r6'], 'ldflags': [ @@ -412,6 +496,29 @@ ], }], ['mips_arch_variant=="r2"', { + 'conditions': [ + [ 'mips_fpu_mode=="fp64"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP64', + ], + 'cflags': ['-mfp64'], + }], + ['mips_fpu_mode=="fpxx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FPXX', + ], + 'cflags': ['-mfpxx'], + }], + ['mips_fpu_mode=="fp32"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP32', + ], + 'cflags': ['-mfp32'], + }], + ], 'cflags': ['-mips32r2', '-Wa,-mips32r2'], 'ldflags': ['-mips32r2'], }], @@ -421,67 +528,122 @@ 'ldflags': ['-mips32'], }], ['mips_arch_variant=="rx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32RX', + 'FPU_MODE_FPXX', + ], 'cflags!': ['-mfp64', '-mfp32'], 'cflags': ['-mips32', '-Wa,-mips32', '-mfpxx'], 'ldflags': ['-mips32'], }], ['mips_arch_variant=="loongson"', { + 'defines': [ + '_MIPS_ARCH_LOONGSON', + 'FPU_MODE_FP32', + ], 'cflags!': ['-mfp64', '-mfp32', '-mfpxx'], 'cflags': ['-mips3', '-Wa,-mips3'], }], ], + }, { + # 'v8_target_arch!=target_arch' + # Target not built with an MIPS CXX compiler (simulator build). + 'conditions': [ + ['mips_arch_variant=="r6"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R6', + 'FPU_MODE_FP64', + ], + }], + ['mips_arch_variant=="r2"', { + 'conditions': [ + [ 'mips_fpu_mode=="fp64"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP64', + ], + }], + ['mips_fpu_mode=="fpxx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FPXX', + ], + }], + ['mips_fpu_mode=="fp32"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP32', + ], + }], + ], + }], + ['mips_arch_variant=="r1"', { + 'defines': [ + 'FPU_MODE_FP32', + ], + }], + ['mips_arch_variant=="rx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32RX', + 'FPU_MODE_FPXX', + ], + }], + ['mips_arch_variant=="loongson"', { + 'defines': [ + '_MIPS_ARCH_LOONGSON', + 'FPU_MODE_FP32', + ], + }], + ], }], ], - }], - [ 'v8_can_use_fpu_instructions=="true"', { - 'defines': [ - 'CAN_USE_FPU_INSTRUCTIONS', - ], - }], - [ 'v8_use_mips_abi_hardfloat=="true"', { - 'defines': [ - '__mips_hard_float=1', - 'CAN_USE_FPU_INSTRUCTIONS', - ], - }, { - 'defines': [ - '__mips_soft_float=1' - ], - }], - ['mips_arch_variant=="rx"', { - 'defines': [ - '_MIPS_ARCH_MIPS32RX', - 'FPU_MODE_FPXX', - ], - }], - ['mips_arch_variant=="r6"', { - 'defines': [ - '_MIPS_ARCH_MIPS32R6', - 'FPU_MODE_FP64', - ], - }], - ['mips_arch_variant=="r2"', { - 'defines': ['_MIPS_ARCH_MIPS32R2',], + }], #_toolset=="target + ['_toolset=="host"', { 'conditions': [ - ['mips_fpu_mode=="fp64"', { - 'defines': ['FPU_MODE_FP64',], + ['mips_arch_variant=="rx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32RX', + 'FPU_MODE_FPXX', + ], }], - ['mips_fpu_mode=="fpxx"', { - 'defines': ['FPU_MODE_FPXX',], + ['mips_arch_variant=="r6"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R6', + 'FPU_MODE_FP64', + ], }], - ['mips_fpu_mode=="fp32"', { + ['mips_arch_variant=="r2"', { + 'conditions': [ + ['mips_fpu_mode=="fp64"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP64', + ], + }], + ['mips_fpu_mode=="fpxx"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FPXX', + ], + }], + ['mips_fpu_mode=="fp32"', { + 'defines': [ + '_MIPS_ARCH_MIPS32R2', + 'FPU_MODE_FP32' + ], + }], + ], + }], + ['mips_arch_variant=="r1"', { 'defines': ['FPU_MODE_FP32',], }], - ], - }], - ['mips_arch_variant=="r1"', { - 'defines': ['FPU_MODE_FP32',], - }], - ['mips_arch_variant=="loongson"', { - 'defines': [ - '_MIPS_ARCH_LOONGSON', - 'FPU_MODE_FP32', - ], + ['mips_arch_variant=="loongson"', { + 'defines': [ + '_MIPS_ARCH_LOONGSON', + 'FPU_MODE_FP32', + ], + }], + ] }], ], }], # v8_target_arch=="mipsel" @@ -490,40 +652,6 @@ 'V8_TARGET_ARCH_MIPS64', ], 'conditions': [ - ['v8_target_arch==target_arch and android_webview_build==0', { - # Target built with a Mips CXX compiler. - 'target_conditions': [ - ['_toolset=="target"', { - 'cflags': ['-EL'], - 'ldflags': ['-EL'], - 'conditions': [ - [ 'v8_use_mips_abi_hardfloat=="true"', { - 'cflags': ['-mhard-float'], - 'ldflags': ['-mhard-float'], - }, { - 'cflags': ['-msoft-float'], - 'ldflags': ['-msoft-float'], - }], - ['mips_arch_variant=="r6"', { - 'cflags': ['-mips64r6', '-mabi=64', '-Wa,-mips64r6'], - 'ldflags': [ - '-mips64r6', '-mabi=64', - '-Wl,--dynamic-linker=$(LDSO_PATH)', - '-Wl,--rpath=$(LD_R_PATH)', - ], - }], - ['mips_arch_variant=="r2"', { - 'cflags': ['-mips64r2', '-mabi=64', '-Wa,-mips64r2'], - 'ldflags': [ - '-mips64r2', '-mabi=64', - '-Wl,--dynamic-linker=$(LDSO_PATH)', - '-Wl,--rpath=$(LD_R_PATH)', - ], - }], - ], - }], - ], - }], [ 'v8_can_use_fpu_instructions=="true"', { 'defines': [ 'CAN_USE_FPU_INSTRUCTIONS', @@ -539,12 +667,64 @@ '__mips_soft_float=1' ], }], - ['mips_arch_variant=="r6"', { - 'defines': ['_MIPS_ARCH_MIPS64R6',], - }], - ['mips_arch_variant=="r2"', { - 'defines': ['_MIPS_ARCH_MIPS64R2',], - }], + ], + 'target_conditions': [ + ['_toolset=="target"', { + 'conditions': [ + ['v8_target_arch==target_arch and android_webview_build==0', { + 'cflags': ['-EL'], + 'ldflags': ['-EL'], + 'conditions': [ + [ 'v8_use_mips_abi_hardfloat=="true"', { + 'cflags': ['-mhard-float'], + 'ldflags': ['-mhard-float'], + }, { + 'cflags': ['-msoft-float'], + 'ldflags': ['-msoft-float'], + }], + ['mips_arch_variant=="r6"', { + 'defines': ['_MIPS_ARCH_MIPS64R6',], + 'cflags': ['-mips64r6', '-mabi=64', '-Wa,-mips64r6'], + 'ldflags': [ + '-mips64r6', '-mabi=64', + '-Wl,--dynamic-linker=$(LDSO_PATH)', + '-Wl,--rpath=$(LD_R_PATH)', + ], + }], + ['mips_arch_variant=="r2"', { + 'defines': ['_MIPS_ARCH_MIPS64R2',], + 'cflags': ['-mips64r2', '-mabi=64', '-Wa,-mips64r2'], + 'ldflags': [ + '-mips64r2', '-mabi=64', + '-Wl,--dynamic-linker=$(LDSO_PATH)', + '-Wl,--rpath=$(LD_R_PATH)', + ], + }], + ], + }, { + # 'v8_target_arch!=target_arch' + # Target not built with an MIPS CXX compiler (simulator build). + 'conditions': [ + ['mips_arch_variant=="r6"', { + 'defines': ['_MIPS_ARCH_MIPS64R6',], + }], + ['mips_arch_variant=="r2"', { + 'defines': ['_MIPS_ARCH_MIPS64R2',], + }], + ], + }], + ], + }], #'_toolset=="target" + ['_toolset=="host"', { + 'conditions': [ + ['mips_arch_variant=="r6"', { + 'defines': ['_MIPS_ARCH_MIPS64R6',], + }], + ['mips_arch_variant=="r2"', { + 'defines': ['_MIPS_ARCH_MIPS64R2',], + }], + ], + }], #'_toolset=="host" ], }], # v8_target_arch=="mips64el" ['v8_target_arch=="x64"', {
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index e0750cd..d294785 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc
@@ -234,61 +234,6 @@ } -void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( - Isolate* isolate) { - WriteInt32ToHeapNumberStub stub1(isolate, r1, r0, r2); - WriteInt32ToHeapNumberStub stub2(isolate, r2, r0, r3); - stub1.GetCode(); - stub2.GetCode(); -} - - -// See comment for class. -void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { - Label max_negative_int; - // the_int_ has the answer which is a signed int32 but not a Smi. - // We test for the special value that has a different exponent. This test - // has the neat side effect of setting the flags according to the sign. - STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); - __ cmp(the_int(), Operand(0x80000000u)); - __ b(eq, &max_negative_int); - // Set up the correct exponent in scratch_. All non-Smi int32s have the same. - // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). - uint32_t non_smi_exponent = - (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; - __ mov(scratch(), Operand(non_smi_exponent)); - // Set the sign bit in scratch_ if the value was negative. - __ orr(scratch(), scratch(), Operand(HeapNumber::kSignMask), LeaveCC, cs); - // Subtract from 0 if the value was negative. - __ rsb(the_int(), the_int(), Operand::Zero(), LeaveCC, cs); - // We should be masking the implict first digit of the mantissa away here, - // but it just ends up combining harmlessly with the last digit of the - // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get - // the most significant 1 to hit the last bit of the 12 bit sign and exponent. - DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); - const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; - __ orr(scratch(), scratch(), Operand(the_int(), LSR, shift_distance)); - __ str(scratch(), - FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); - __ mov(scratch(), Operand(the_int(), LSL, 32 - shift_distance)); - __ str(scratch(), - FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); - __ Ret(); - - __ bind(&max_negative_int); - // The max negative int32 is stored as a positive number in the mantissa of - // a double because it uses a sign bit instead of using two's complement. - // The actual mantissa bits stored are all 0 because the implicit most - // significant 1 bit is not stored. - non_smi_exponent += 1 << HeapNumber::kExponentShift; - __ mov(ip, Operand(HeapNumber::kSignMask | non_smi_exponent)); - __ str(ip, FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); - __ mov(ip, Operand::Zero()); - __ str(ip, FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); - __ Ret(); -} - - // Handle the case where the lhs and rhs are the same object. // Equality is almost reflexive (everything but NaN), so this is a test // for "identity and not NaN". @@ -967,7 +912,6 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { CEntryStub::GenerateAheadOfTime(isolate); - WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); StubFailureTrampolineStub::GenerateAheadOfTime(isolate); ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
diff --git a/src/arm/code-stubs-arm.h b/src/arm/code-stubs-arm.h index 727bb1b..7f00cc0 100644 --- a/src/arm/code-stubs-arm.h +++ b/src/arm/code-stubs-arm.h
@@ -46,44 +46,6 @@ }; -// This stub can convert a signed int32 to a heap number (double). It does -// not work for int32s that are in Smi range! No GC occurs during this stub -// so you don't have to set up the frame. -class WriteInt32ToHeapNumberStub : public PlatformCodeStub { - public: - WriteInt32ToHeapNumberStub(Isolate* isolate, Register the_int, - Register the_heap_number, Register scratch) - : PlatformCodeStub(isolate) { - minor_key_ = IntRegisterBits::encode(the_int.code()) | - HeapNumberRegisterBits::encode(the_heap_number.code()) | - ScratchRegisterBits::encode(scratch.code()); - } - - static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); - - private: - Register the_int() const { - return Register::from_code(IntRegisterBits::decode(minor_key_)); - } - - Register the_heap_number() const { - return Register::from_code(HeapNumberRegisterBits::decode(minor_key_)); - } - - Register scratch() const { - return Register::from_code(ScratchRegisterBits::decode(minor_key_)); - } - - // Minor key encoding in 16 bits. - class IntRegisterBits: public BitField<int, 0, 4> {}; - class HeapNumberRegisterBits: public BitField<int, 4, 4> {}; - class ScratchRegisterBits: public BitField<int, 8, 4> {}; - - DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); - DEFINE_PLATFORM_CODE_STUB(WriteInt32ToHeapNumber, PlatformCodeStub); -}; - - class RecordWriteStub: public PlatformCodeStub { public: RecordWriteStub(Isolate* isolate,
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index e945a13..e323e0d 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc
@@ -2964,6 +2964,7 @@ __ add(sp, sp, Operand(sp_delta)); } } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register reg = ToRegister(instr->parameter_count()); // The argument count parameter is a smi __ SmiUntag(reg);
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc index 1b8ae1b..9fe311c 100644 --- a/src/arm64/lithium-codegen-arm64.cc +++ b/src/arm64/lithium-codegen-arm64.cc
@@ -4766,6 +4766,7 @@ int parameter_count = ToInteger32(instr->constant_parameter_count()); __ Drop(parameter_count + 1); } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register parameter_count = ToRegister(instr->parameter_count()); __ DropBySMI(parameter_count); }
diff --git a/src/code-stubs.h b/src/code-stubs.h index 13f8e42..af5ae8d 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h
@@ -92,9 +92,7 @@ // List of code stubs only used on ARM 32 bits platforms. #if V8_TARGET_ARCH_ARM -#define CODE_STUB_LIST_ARM(V) \ - V(DirectCEntry) \ - V(WriteInt32ToHeapNumber) +#define CODE_STUB_LIST_ARM(V) V(DirectCEntry) #else #define CODE_STUB_LIST_ARM(V) @@ -113,17 +111,15 @@ // List of code stubs only used on MIPS platforms. #if V8_TARGET_ARCH_MIPS -#define CODE_STUB_LIST_MIPS(V) \ - V(DirectCEntry) \ - V(RestoreRegistersState) \ - V(StoreRegistersState) \ - V(WriteInt32ToHeapNumber) +#define CODE_STUB_LIST_MIPS(V) \ + V(DirectCEntry) \ + V(RestoreRegistersState) \ + V(StoreRegistersState) #elif V8_TARGET_ARCH_MIPS64 -#define CODE_STUB_LIST_MIPS(V) \ - V(DirectCEntry) \ - V(RestoreRegistersState) \ - V(StoreRegistersState) \ - V(WriteInt32ToHeapNumber) +#define CODE_STUB_LIST_MIPS(V) \ + V(DirectCEntry) \ + V(RestoreRegistersState) \ + V(StoreRegistersState) #else #define CODE_STUB_LIST_MIPS(V) #endif
diff --git a/src/compiler/basic-block-instrumentor.cc b/src/compiler/basic-block-instrumentor.cc index 708ec49..59bb7f4 100644 --- a/src/compiler/basic-block-instrumentor.cc +++ b/src/compiler/basic-block-instrumentor.cc
@@ -69,7 +69,7 @@ CommonOperatorBuilder common(graph->zone()); Node* zero = graph->NewNode(common.Int32Constant(0)); Node* one = graph->NewNode(common.Int32Constant(1)); - MachineOperatorBuilder machine; + MachineOperatorBuilder machine(graph->zone()); BasicBlockVector* blocks = schedule->rpo_order(); size_t block_number = 0; for (BasicBlockVector::iterator it = blocks->begin(); block_number < n_blocks;
diff --git a/src/compiler/instruction.h b/src/compiler/instruction.h index b6fcb3c..8a6006a 100644 --- a/src/compiler/instruction.h +++ b/src/compiler/instruction.h
@@ -332,6 +332,11 @@ return reinterpret_cast<SubKindOperand*>(op); } + static const SubKindOperand* cast(const InstructionOperand* op) { + DCHECK(op->kind() == kOperandKind); + return reinterpret_cast<const SubKindOperand*>(op); + } + static void SetUpCache(); static void TearDownCache(); @@ -581,7 +586,7 @@ return parallel_moves_[pos]; } - ParallelMove* GetParallelMove(InnerPosition pos) { + ParallelMove* GetParallelMove(InnerPosition pos) const { return parallel_moves_[pos]; } @@ -917,6 +922,7 @@ typedef InstructionDeque::const_iterator const_iterator; const_iterator begin() const { return instructions_.begin(); } const_iterator end() const { return instructions_.end(); } + const InstructionDeque& instructions() const { return instructions_; } GapInstruction* GapAt(int index) const { return GapInstruction::cast(InstructionAt(index));
diff --git a/src/compiler/machine-operator.cc b/src/compiler/machine-operator.cc index 2ea1bf3..83459f7 100644 --- a/src/compiler/machine-operator.cc +++ b/src/compiler/machine-operator.cc
@@ -7,6 +7,8 @@ #include "src/base/lazy-instance.h" #include "src/compiler/opcodes.h" #include "src/compiler/operator.h" +#include "src/v8.h" +#include "src/zone-inl.h" namespace v8 { namespace internal { @@ -196,8 +198,9 @@ LAZY_INSTANCE_INITIALIZER; -MachineOperatorBuilder::MachineOperatorBuilder(MachineType word, Flags flags) - : cache_(kCache.Get()), word_(word), flags_(flags) { +MachineOperatorBuilder::MachineOperatorBuilder(Zone* zone, MachineType word, + Flags flags) + : zone_(zone), cache_(kCache.Get()), word_(word), flags_(flags) { DCHECK(word == kRepWord32 || word == kRepWord64); } @@ -220,8 +223,10 @@ default: break; } - UNREACHABLE(); - return NULL; + // Uncached. + return new (zone_) Operator1<LoadRepresentation>( // -- + IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite, "Load", 2, 1, 1, + 1, 1, 0, rep); } @@ -242,8 +247,10 @@ default: break; } - UNREACHABLE(); - return NULL; + // Uncached. + return new (zone_) Operator1<StoreRepresentation>( // -- + IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow, "Store", 3, 1, + 1, 0, 1, 0, rep); } } // namespace compiler } // namespace internal
diff --git a/src/compiler/machine-operator.h b/src/compiler/machine-operator.h index 979a887..8c0d11a 100644 --- a/src/compiler/machine-operator.h +++ b/src/compiler/machine-operator.h
@@ -73,7 +73,7 @@ }; typedef base::Flags<Flag, unsigned> Flags; - explicit MachineOperatorBuilder(MachineType word = kMachPtr, + explicit MachineOperatorBuilder(Zone* zone, MachineType word = kMachPtr, Flags supportedOperators = kNoFlags); const Operator* Word32And(); @@ -211,6 +211,7 @@ #undef PSEUDO_OP_LIST private: + Zone* zone_; const MachineOperatorGlobalCache& cache_; const MachineType word_; const Flags flags_;
diff --git a/src/compiler/node.h b/src/compiler/node.h index 3a5afd2..8a442ce 100644 --- a/src/compiler/node.h +++ b/src/compiler/node.h
@@ -68,6 +68,8 @@ typedef NodeSet::iterator NodeSetIter; typedef NodeSet::reverse_iterator NodeSetRIter; +typedef ZoneDeque<Node*> NodeDeque; + typedef ZoneVector<Node*> NodeVector; typedef NodeVector::iterator NodeVectorIter; typedef NodeVector::const_iterator NodeVectorConstIter;
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc index f2571e3..5832905 100644 --- a/src/compiler/pipeline.cc +++ b/src/compiler/pipeline.cc
@@ -53,7 +53,8 @@ graph_(new (graph_zone()) Graph(graph_zone())), source_positions_(new SourcePositionTable(graph())), machine_(new (graph_zone()) MachineOperatorBuilder( - kMachPtr, InstructionSelector::SupportedMachineOperatorFlags())), + graph_zone(), kMachPtr, + InstructionSelector::SupportedMachineOperatorFlags())), common_(new (graph_zone()) CommonOperatorBuilder(graph_zone())), javascript_(new (graph_zone()) JSOperatorBuilder(graph_zone())), jsgraph_(new (graph_zone()) @@ -584,15 +585,17 @@ ZonePool::Scope zone_scope(data->zone_pool()); SmartArrayPointer<char> debug_name; + RegisterAllocator::VerificationType verification_type = + RegisterAllocator::kNoVerify; #ifdef DEBUG debug_name = GetDebugName(info()); + verification_type = RegisterAllocator::kVerifyAssignment; #endif - RegisterAllocator allocator(RegisterConfiguration::ArchDefault(), zone_scope.zone(), &frame, &sequence, debug_name.get()); - if (!allocator.Allocate(data->pipeline_statistics())) { + if (!allocator.Allocate(data->pipeline_statistics(), verification_type)) { info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc); return Handle<Code>::null(); }
diff --git a/src/compiler/raw-machine-assembler.cc b/src/compiler/raw-machine-assembler.cc index a8b658f..0327d1c 100644 --- a/src/compiler/raw-machine-assembler.cc +++ b/src/compiler/raw-machine-assembler.cc
@@ -17,7 +17,7 @@ MachineOperatorBuilder::Flags flags) : GraphBuilder(graph), schedule_(new (zone()) Schedule(zone())), - machine_(word, flags), + machine_(zone(), word, flags), common_(zone()), machine_sig_(machine_sig), call_descriptor_(
diff --git a/src/compiler/register-allocator-verifier.cc b/src/compiler/register-allocator-verifier.cc new file mode 100644 index 0000000..b8aefe1 --- /dev/null +++ b/src/compiler/register-allocator-verifier.cc
@@ -0,0 +1,179 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/compiler/instruction.h" +#include "src/compiler/register-allocator-verifier.h" + +namespace v8 { +namespace internal { +namespace compiler { + +static size_t OperandCount(const Instruction* instr) { + return instr->InputCount() + instr->OutputCount() + instr->TempCount(); +} + + +RegisterAllocatorVerifier::RegisterAllocatorVerifier( + Zone* zone, const InstructionSequence* sequence) + : sequence_(sequence), constraints_(zone) { + constraints_.reserve(sequence->instructions().size()); + for (const auto* instr : sequence->instructions()) { + const size_t operand_count = OperandCount(instr); + auto* op_constraints = + zone->NewArray<OperandConstraint>(static_cast<int>(operand_count)); + // Construct OperandConstraints for all InstructionOperands, eliminating + // kSameAsFirst along the way. + size_t count = 0; + for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { + BuildConstraint(instr->InputAt(i), &op_constraints[count]); + CHECK_NE(kSameAsFirst, op_constraints[count].type_); + } + for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { + BuildConstraint(instr->OutputAt(i), &op_constraints[count]); + if (op_constraints[count].type_ == kSameAsFirst) { + CHECK(instr->InputCount() > 0); + op_constraints[count] = op_constraints[0]; + } + } + for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { + BuildConstraint(instr->TempAt(i), &op_constraints[count]); + CHECK_NE(kSameAsFirst, op_constraints[count].type_); + } + // All gaps should be totally unallocated at this point. + if (instr->IsGapMoves()) { + const auto* gap = GapInstruction::cast(instr); + for (int i = GapInstruction::FIRST_INNER_POSITION; + i <= GapInstruction::LAST_INNER_POSITION; i++) { + GapInstruction::InnerPosition inner_pos = + static_cast<GapInstruction::InnerPosition>(i); + CHECK_EQ(NULL, gap->GetParallelMove(inner_pos)); + } + } + InstructionConstraint instr_constraint = {instr, operand_count, + op_constraints}; + constraints()->push_back(instr_constraint); + } +} + + +void RegisterAllocatorVerifier::VerifyAssignment() { + CHECK(sequence()->instructions().size() == constraints()->size()); + auto instr_it = sequence()->begin(); + for (const auto& instr_constraint : *constraints()) { + const auto* instr = instr_constraint.instruction_; + const size_t operand_count = instr_constraint.operand_constaints_size_; + const auto* op_constraints = instr_constraint.operand_constraints_; + CHECK_EQ(instr, *instr_it); + CHECK(operand_count == OperandCount(instr)); + size_t count = 0; + for (size_t i = 0; i < instr->InputCount(); ++i, ++count) { + CheckConstraint(instr->InputAt(i), &op_constraints[count]); + } + for (size_t i = 0; i < instr->OutputCount(); ++i, ++count) { + CheckConstraint(instr->OutputAt(i), &op_constraints[count]); + } + for (size_t i = 0; i < instr->TempCount(); ++i, ++count) { + CheckConstraint(instr->TempAt(i), &op_constraints[count]); + } + ++instr_it; + } +} + + +void RegisterAllocatorVerifier::BuildConstraint(const InstructionOperand* op, + OperandConstraint* constraint) { + constraint->value_ = kMinInt; + if (op->IsConstant()) { + constraint->type_ = kConstant; + constraint->value_ = ConstantOperand::cast(op)->index(); + } else if (op->IsImmediate()) { + constraint->type_ = kImmediate; + constraint->value_ = ImmediateOperand::cast(op)->index(); + } else { + CHECK(op->IsUnallocated()); + const auto* unallocated = UnallocatedOperand::cast(op); + int vreg = unallocated->virtual_register(); + if (unallocated->basic_policy() == UnallocatedOperand::FIXED_SLOT) { + constraint->type_ = kFixedSlot; + constraint->value_ = unallocated->fixed_slot_index(); + } else { + switch (unallocated->extended_policy()) { + case UnallocatedOperand::ANY: + CHECK(false); + break; + case UnallocatedOperand::NONE: + if (sequence()->IsDouble(vreg)) { + constraint->type_ = kNoneDouble; + } else { + constraint->type_ = kNone; + } + break; + case UnallocatedOperand::FIXED_REGISTER: + constraint->type_ = kFixedRegister; + constraint->value_ = unallocated->fixed_register_index(); + break; + case UnallocatedOperand::FIXED_DOUBLE_REGISTER: + constraint->type_ = kFixedDoubleRegister; + constraint->value_ = unallocated->fixed_register_index(); + break; + case UnallocatedOperand::MUST_HAVE_REGISTER: + if (sequence()->IsDouble(vreg)) { + constraint->type_ = kDoubleRegister; + } else { + constraint->type_ = kRegister; + } + break; + case UnallocatedOperand::SAME_AS_FIRST_INPUT: + constraint->type_ = kSameAsFirst; + break; + } + } + } +} + + +void RegisterAllocatorVerifier::CheckConstraint( + const InstructionOperand* op, const OperandConstraint* constraint) { + switch (constraint->type_) { + case kConstant: + CHECK(op->IsConstant()); + CHECK_EQ(op->index(), constraint->value_); + return; + case kImmediate: + CHECK(op->IsImmediate()); + CHECK_EQ(op->index(), constraint->value_); + return; + case kRegister: + CHECK(op->IsRegister()); + return; + case kFixedRegister: + CHECK(op->IsRegister()); + CHECK_EQ(op->index(), constraint->value_); + return; + case kDoubleRegister: + CHECK(op->IsDoubleRegister()); + return; + case kFixedDoubleRegister: + CHECK(op->IsDoubleRegister()); + CHECK_EQ(op->index(), constraint->value_); + return; + case kFixedSlot: + CHECK(op->IsStackSlot()); + CHECK_EQ(op->index(), constraint->value_); + return; + case kNone: + CHECK(op->IsRegister() || op->IsStackSlot()); + return; + case kNoneDouble: + CHECK(op->IsDoubleRegister() || op->IsDoubleStackSlot()); + return; + case kSameAsFirst: + CHECK(false); + return; + } +} + +} // namespace compiler +} // namespace internal +} // namespace v8
diff --git a/src/compiler/register-allocator-verifier.h b/src/compiler/register-allocator-verifier.h new file mode 100644 index 0000000..10592e1 --- /dev/null +++ b/src/compiler/register-allocator-verifier.h
@@ -0,0 +1,68 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_REGISTER_ALLOCATOR_VERIFIER_H_ +#define V8_REGISTER_ALLOCATOR_VERIFIER_H_ + +#include "src/v8.h" +#include "src/zone-containers.h" + +namespace v8 { +namespace internal { +namespace compiler { + +class InstructionOperand; +class InstructionSequence; + +class RegisterAllocatorVerifier FINAL : public ZoneObject { + public: + RegisterAllocatorVerifier(Zone* zone, const InstructionSequence* sequence); + + void VerifyAssignment(); + + private: + enum ConstraintType { + kConstant, + kImmediate, + kRegister, + kFixedRegister, + kDoubleRegister, + kFixedDoubleRegister, + kFixedSlot, + kNone, + kNoneDouble, + kSameAsFirst + }; + + struct OperandConstraint { + ConstraintType type_; + int value_; // subkind index when relevant + }; + + struct InstructionConstraint { + const Instruction* instruction_; + size_t operand_constaints_size_; + OperandConstraint* operand_constraints_; + }; + + typedef ZoneVector<InstructionConstraint> Constraints; + + const InstructionSequence* sequence() const { return sequence_; } + Constraints* constraints() { return &constraints_; } + void BuildConstraint(const InstructionOperand* op, + OperandConstraint* constraint); + void CheckConstraint(const InstructionOperand* op, + const OperandConstraint* constraint); + + const InstructionSequence* const sequence_; + Constraints constraints_; + + DISALLOW_COPY_AND_ASSIGN(RegisterAllocatorVerifier); +}; + +} // namespace compiler +} // namespace internal +} // namespace v8 + +#endif
diff --git a/src/compiler/register-allocator.cc b/src/compiler/register-allocator.cc index 23a7df6..0069df8 100644 --- a/src/compiler/register-allocator.cc +++ b/src/compiler/register-allocator.cc
@@ -5,6 +5,7 @@ #include "src/compiler/linkage.h" #include "src/compiler/pipeline-statistics.h" #include "src/compiler/register-allocator.h" +#include "src/compiler/register-allocator-verifier.h" #include "src/string-stream.h" namespace v8 { @@ -1116,7 +1117,16 @@ } -bool RegisterAllocator::Allocate(PipelineStatistics* stats) { +bool RegisterAllocator::Allocate(PipelineStatistics* stats, + VerificationType verification_type) { + SmartPointer<Zone> verifier_zone; + RegisterAllocatorVerifier* verifier = NULL; + if (verification_type == kVerifyAssignment) { + // Don't track usage for this zone in compiler stats. + verifier_zone.Reset(new Zone(local_zone()->isolate())); + verifier = new (verifier_zone.get()) + RegisterAllocatorVerifier(verifier_zone.get(), code()); + } assigned_registers_ = new (code_zone()) BitVector(config()->num_general_registers(), code_zone()); assigned_double_registers_ = new (code_zone()) @@ -1158,6 +1168,9 @@ } frame()->SetAllocatedRegisters(assigned_registers_); frame()->SetAllocatedDoubleRegisters(assigned_double_registers_); + if (verifier != NULL) { + verifier->VerifyAssignment(); + } return true; }
diff --git a/src/compiler/register-allocator.h b/src/compiler/register-allocator.h index a6578af..690957d 100644 --- a/src/compiler/register-allocator.h +++ b/src/compiler/register-allocator.h
@@ -322,12 +322,15 @@ class RegisterAllocator FINAL { public: + enum VerificationType { kNoVerify, kVerifyAssignment }; + explicit RegisterAllocator(const RegisterConfiguration* config, Zone* local_zone, Frame* frame, InstructionSequence* code, const char* debug_name = nullptr); - bool Allocate(PipelineStatistics* stats = NULL); + bool Allocate(PipelineStatistics* stats = NULL, + VerificationType verification_type = kNoVerify); bool AllocationOk() { return allocation_ok_; } BitVector* assigned_registers() { return assigned_registers_; } BitVector* assigned_double_registers() { return assigned_double_registers_; }
diff --git a/src/compiler/select-lowering.cc b/src/compiler/select-lowering.cc index 2e51d72..cb2b042 100644 --- a/src/compiler/select-lowering.cc +++ b/src/compiler/select-lowering.cc
@@ -26,26 +26,61 @@ if (node->opcode() != IrOpcode::kSelect) return NoChange(); SelectParameters const p = SelectParametersOf(node->op()); - Node* const cond = node->InputAt(0); + Node* cond = node->InputAt(0); + Node* vthen = node->InputAt(1); + Node* velse = node->InputAt(2); + Node* merge = nullptr; // Check if we already have a diamond for this condition. - auto i = merges_.find(cond); - if (i == merges_.end()) { - // Create a new diamond for this condition and remember its merge node. - Diamond d(graph(), common(), cond, p.hint()); - i = merges_.insert(std::make_pair(cond, d.merge)).first; - } + auto range = merges_.equal_range(cond); + for (auto i = range.first;; ++i) { + if (i == range.second) { + // Create a new diamond for this condition and remember its merge node. + Diamond d(graph(), common(), cond, p.hint()); + merges_.insert(std::make_pair(cond, d.merge)); + merge = d.merge; + break; + } - DCHECK_EQ(cond, i->first); + // If the diamond is reachable from the Select, merging them would result in + // an unschedulable graph, so we cannot reuse the diamond in that case. + merge = i->second; + if (!ReachableFrom(merge, node)) { + break; + } + } // Create a Phi hanging off the previously determined merge. node->set_op(common()->Phi(p.type(), 2)); - node->ReplaceInput(0, node->InputAt(1)); - node->ReplaceInput(1, node->InputAt(2)); - node->ReplaceInput(2, i->second); + node->ReplaceInput(0, vthen); + node->ReplaceInput(1, velse); + node->ReplaceInput(2, merge); return Changed(node); } + +bool SelectLowering::ReachableFrom(Node* const sink, Node* const source) { + // TODO(turbofan): This is probably horribly expensive, and it should be moved + // into node.h or somewhere else?! + Zone zone(graph()->zone()->isolate()); + std::queue<Node*, NodeDeque> queue((NodeDeque(&zone))); + BoolVector visited(graph()->NodeCount(), false, &zone); + queue.push(source); + visited[source->id()] = true; + while (!queue.empty()) { + Node* current = queue.front(); + if (current == sink) return true; + queue.pop(); + for (auto input : current->inputs()) { + if (!visited[input->id()]) { + queue.push(input); + visited[input->id()] = true; + } + } + } + return false; +} + } // namespace compiler } // namespace internal } // namespace v8
diff --git a/src/compiler/select-lowering.h b/src/compiler/select-lowering.h index ae22cad..05ea0e0 100644 --- a/src/compiler/select-lowering.h +++ b/src/compiler/select-lowering.h
@@ -28,8 +28,10 @@ Reduction Reduce(Node* node) OVERRIDE; private: - typedef std::map<Node*, Node*, std::less<Node*>, - zone_allocator<std::pair<Node* const, Node*>>> Merges; + typedef std::multimap<Node*, Node*, std::less<Node*>, + zone_allocator<std::pair<Node* const, Node*>>> Merges; + + bool ReachableFrom(Node* const sink, Node* const source); CommonOperatorBuilder* common() const { return common_; } Graph* graph() const { return graph_; }
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc index c50b338..33a3077 100644 --- a/src/compiler/simplified-lowering.cc +++ b/src/compiler/simplified-lowering.cc
@@ -672,8 +672,11 @@ VisitUnop(node, kTypeInt32 | use_rep, kTypeInt32 | use_rep); if (lower()) DeferReplacement(node, node->InputAt(0)); } else if ((in & kTypeMask) == kTypeUint32 || - (in & kTypeMask) == kTypeInt32 || - in_upper->Is(Type::Unsigned32()) || + in_upper->Is(Type::Unsigned32())) { + // Just change representation if necessary. + VisitUnop(node, kTypeUint32 | kRepWord32, kTypeInt32 | kRepWord32); + if (lower()) DeferReplacement(node, node->InputAt(0)); + } else if ((in & kTypeMask) == kTypeInt32 || (in & kRepMask) == kRepWord32) { // Just change representation if necessary. VisitUnop(node, kTypeInt32 | kRepWord32, kTypeInt32 | kRepWord32); @@ -697,12 +700,15 @@ VisitUnop(node, kTypeUint32 | use_rep, kTypeUint32 | use_rep); if (lower()) DeferReplacement(node, node->InputAt(0)); } else if ((in & kTypeMask) == kTypeUint32 || - (in & kTypeMask) == kTypeInt32 || - in_upper->Is(Type::Signed32()) || - (in & kRepMask) == kRepWord32) { + in_upper->Is(Type::Unsigned32())) { // Just change representation if necessary. VisitUnop(node, kTypeUint32 | kRepWord32, kTypeUint32 | kRepWord32); if (lower()) DeferReplacement(node, node->InputAt(0)); + } else if ((in & kTypeMask) == kTypeInt32 || + (in & kRepMask) == kRepWord32) { + // Just change representation if necessary. + VisitUnop(node, kTypeInt32 | kRepWord32, kTypeUint32 | kRepWord32); + if (lower()) DeferReplacement(node, node->InputAt(0)); } else { // Require the input in float64 format and perform truncation. // TODO(turbofan): avoid a truncation with a smi check.
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 0fa2b95..99f4f89 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc
@@ -1033,8 +1033,7 @@ lhs = Rangify(lhs, t); rhs = Rangify(rhs, t); if (lhs->IsRange() && rhs->IsRange()) { - // TODO(titzer): fix me. - // return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); + return JSModulusRanger(lhs->AsRange(), rhs->AsRange(), t); } return Type::OrderedNumber(); }
diff --git a/src/contexts.h b/src/contexts.h index 716682d..8182532 100644 --- a/src/contexts.h +++ b/src/contexts.h
@@ -413,13 +413,13 @@ UNSCOPABLES_SYMBOL_INDEX, ARRAY_VALUES_ITERATOR_INDEX, GLOBAL_CONTEXT_TABLE_INDEX, + MAP_CACHE_INDEX, // Properties from here are treated as weak references by the full GC. // Scavenge treats them as strong references. OPTIMIZED_FUNCTIONS_LIST, // Weak. OPTIMIZED_CODE_LIST, // Weak. DEOPTIMIZED_CODE_LIST, // Weak. - MAP_CACHE_INDEX, // Weak. NEXT_CONTEXT_LINK, // Weak. // Total number of slots.
diff --git a/src/factory.cc b/src/factory.cc index 796fd13..e68ac9b 100644 --- a/src/factory.cc +++ b/src/factory.cc
@@ -2420,35 +2420,42 @@ } -Handle<MapCache> Factory::AddToMapCache(Handle<Context> context, - Handle<FixedArray> keys, - Handle<Map> map) { - Handle<MapCache> map_cache = handle(MapCache::cast(context->map_cache())); - Handle<MapCache> result = MapCache::Put(map_cache, keys, map); - context->set_map_cache(*result); - return result; -} - - Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context, - Handle<FixedArray> keys) { + int number_of_properties, + bool* is_result_from_cache) { + const int kMapCacheSize = 128; + + if (number_of_properties > kMapCacheSize) { + *is_result_from_cache = false; + return Map::Create(isolate(), number_of_properties); + } + *is_result_from_cache = true; + if (number_of_properties == 0) { + // Reuse the initial map of the Object function if the literal has no + // predeclared properties. + return handle(context->object_function()->initial_map(), isolate()); + } + int cache_index = number_of_properties - 1; if (context->map_cache()->IsUndefined()) { // Allocate the new map cache for the native context. - Handle<MapCache> new_cache = MapCache::New(isolate(), 24); + Handle<FixedArray> new_cache = NewFixedArray(kMapCacheSize, TENURED); context->set_map_cache(*new_cache); } // Check to see whether there is a matching element in the cache. - Handle<MapCache> cache = - Handle<MapCache>(MapCache::cast(context->map_cache())); - Handle<Object> result = Handle<Object>(cache->Lookup(*keys), isolate()); - if (result->IsMap()) return Handle<Map>::cast(result); - int length = keys->length(); - // Create a new map and add it to the cache. Reuse the initial map of the - // Object function if the literal has no predeclared properties. - Handle<Map> map = length == 0 - ? handle(context->object_function()->initial_map()) - : Map::Create(isolate(), length); - AddToMapCache(context, keys, map); + Handle<FixedArray> cache(FixedArray::cast(context->map_cache())); + { + Object* result = cache->get(cache_index); + if (result->IsWeakCell()) { + WeakCell* cell = WeakCell::cast(result); + if (!cell->cleared()) { + return handle(Map::cast(cell->value()), isolate()); + } + } + } + // Create a new map and add it to the cache. + Handle<Map> map = Map::Create(isolate(), number_of_properties); + Handle<WeakCell> cell = NewWeakCell(map); + cache->set(cache_index, *cell); return map; } @@ -2467,6 +2474,7 @@ regexp->set_data(*store); } + void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp, JSRegExp::Type type, Handle<String> source, @@ -2488,7 +2496,6 @@ } - MaybeHandle<FunctionTemplateInfo> Factory::ConfigureInstance( Handle<FunctionTemplateInfo> desc, Handle<JSObject> instance) { // Configure the instance by adding the properties specified by the
diff --git a/src/factory.h b/src/factory.h index 6a9ee55..44bb1be 100644 --- a/src/factory.h +++ b/src/factory.h
@@ -643,10 +643,11 @@ Handle<DebugInfo> NewDebugInfo(Handle<SharedFunctionInfo> shared); - // Return a map using the map cache in the native context. - // The key the an ordered set of property names. + // Return a map for given number of properties using the map cache in the + // native context. Handle<Map> ObjectLiteralMapFromCache(Handle<Context> context, - Handle<FixedArray> keys); + int number_of_properties, + bool* is_result_from_cache); // Creates a new FixedArray that holds the data associated with the // atom regexp and stores it in the regexp. @@ -689,14 +690,6 @@ // Creates a code object that is not yet fully initialized yet. inline Handle<Code> NewCodeRaw(int object_size, bool immovable); - // Create a new map cache. - Handle<MapCache> NewMapCache(int at_least_space_for); - - // Update the map cache in the native context with (keys, map) - Handle<MapCache> AddToMapCache(Handle<Context> context, - Handle<FixedArray> keys, - Handle<Map> map); - // Attempt to find the number in a small cache. If we finds it, return // the string representation of the number. Otherwise return undefined. Handle<Object> GetNumberStringCache(Handle<Object> number);
diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 7f217bb..df99de4 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc
@@ -1282,7 +1282,7 @@ Context::FIRST_WEAK_SLOT); STATIC_ASSERT(Context::NEXT_CONTEXT_LINK + 1 == Context::NATIVE_CONTEXT_SLOTS); - STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 5 == + STATIC_ASSERT(Context::FIRST_WEAK_SLOT + 4 == Context::NATIVE_CONTEXT_SLOTS); } }
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc index 2cefebf..b929d85 100644 --- a/src/heap/mark-compact.cc +++ b/src/heap/mark-compact.cc
@@ -2232,12 +2232,6 @@ void MarkCompactCollector::AfterMarking() { - // Object literal map caches reference strings (cache keys) and maps - // (cache values). At this point still useful maps have already been - // marked. Mark the keys for the alive values before we process the - // string table. - ProcessMapCaches(); - // Prune the string table removing all strings only pointed to by the // string table. Cannot use string_table() here because the string // table is marked. @@ -2274,57 +2268,6 @@ } -void MarkCompactCollector::ProcessMapCaches() { - Object* raw_context = heap()->native_contexts_list(); - while (raw_context != heap()->undefined_value()) { - Context* context = reinterpret_cast<Context*>(raw_context); - if (IsMarked(context)) { - HeapObject* raw_map_cache = - HeapObject::cast(context->get(Context::MAP_CACHE_INDEX)); - // A map cache may be reachable from the stack. In this case - // it's already transitively marked and it's too late to clean - // up its parts. - if (!IsMarked(raw_map_cache) && - raw_map_cache != heap()->undefined_value()) { - MapCache* map_cache = reinterpret_cast<MapCache*>(raw_map_cache); - int existing_elements = map_cache->NumberOfElements(); - int used_elements = 0; - for (int i = MapCache::kElementsStartIndex; i < map_cache->length(); - i += MapCache::kEntrySize) { - Object* raw_key = map_cache->get(i); - if (raw_key == heap()->undefined_value() || - raw_key == heap()->the_hole_value()) - continue; - STATIC_ASSERT(MapCache::kEntrySize == 2); - Object* raw_map = map_cache->get(i + 1); - if (raw_map->IsHeapObject() && IsMarked(raw_map)) { - ++used_elements; - } else { - // Delete useless entries with unmarked maps. - DCHECK(raw_map->IsMap()); - map_cache->set_the_hole(i); - map_cache->set_the_hole(i + 1); - } - } - if (used_elements == 0) { - context->set(Context::MAP_CACHE_INDEX, heap()->undefined_value()); - } else { - // Note: we don't actually shrink the cache here to avoid - // extra complexity during GC. We rely on subsequent cache - // usages (EnsureCapacity) to do this. - map_cache->ElementsRemoved(existing_elements - used_elements); - MarkBit map_cache_markbit = Marking::MarkBitFrom(map_cache); - MarkObject(map_cache, map_cache_markbit); - } - } - } - // Move to next element in the list. - raw_context = context->get(Context::NEXT_CONTEXT_LINK); - } - ProcessMarkingDeque(); -} - - void MarkCompactCollector::ClearNonLiveReferences() { // Iterate over the map space, setting map transitions that go from // a marked map to an unmarked map to null transitions. This action
diff --git a/src/heap/mark-compact.h b/src/heap/mark-compact.h index e48d5a3..cd2c9b6 100644 --- a/src/heap/mark-compact.h +++ b/src/heap/mark-compact.h
@@ -786,10 +786,6 @@ // flag on the marking stack. void RefillMarkingDeque(); - // After reachable maps have been marked process per context object - // literal map caches removing unmarked entries. - void ProcessMapCaches(); - // Callback function for telling whether the object *p is an unmarked // heap object. static bool IsUnmarkedHeapObject(Object** p);
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc index ce76fbe..1589066 100644 --- a/src/hydrogen-instructions.cc +++ b/src/hydrogen-instructions.cc
@@ -2834,6 +2834,10 @@ // could cause heap object checks not to get emitted. object_ = Unique<Object>(Handle<Object>::null()); } + if (r.IsSmiOrInteger32()) { + // If it's not a heap object, it can't be in new space. + bit_field_ = IsNotInNewSpaceField::update(bit_field_, true); + } set_representation(r); SetFlag(kUseGVN); }
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index c64a4b0..d6ffbee 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc
@@ -2753,6 +2753,7 @@ } __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register reg = ToRegister(instr->parameter_count()); // The argument count parameter is a smi __ SmiUntag(reg); @@ -2770,6 +2771,7 @@ if (dynamic_frame_alignment) { __ inc(reg); // 1 more for alignment } + __ shl(reg, kPointerSizeLog2); __ add(esp, reg); __ jmp(return_addr_reg);
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 5b34cc2..cfc89d1 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc
@@ -272,66 +272,6 @@ } -void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( - Isolate* isolate) { - WriteInt32ToHeapNumberStub stub1(isolate, a1, v0, a2, a3); - WriteInt32ToHeapNumberStub stub2(isolate, a2, v0, a3, a0); - stub1.GetCode(); - stub2.GetCode(); -} - - -// See comment for class, this does NOT work for int32's that are in Smi range. -void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { - Label max_negative_int; - // the_int_ has the answer which is a signed int32 but not a Smi. - // We test for the special value that has a different exponent. - STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); - // Test sign, and save for later conditionals. - __ And(sign(), the_int(), Operand(0x80000000u)); - __ Branch(&max_negative_int, eq, the_int(), Operand(0x80000000u)); - - // Set up the correct exponent in scratch_. All non-Smi int32s have the same. - // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). - uint32_t non_smi_exponent = - (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; - __ li(scratch(), Operand(non_smi_exponent)); - // Set the sign bit in scratch_ if the value was negative. - __ or_(scratch(), scratch(), sign()); - // Subtract from 0 if the value was negative. - __ subu(at, zero_reg, the_int()); - __ Movn(the_int(), at, sign()); - // We should be masking the implict first digit of the mantissa away here, - // but it just ends up combining harmlessly with the last digit of the - // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get - // the most significant 1 to hit the last bit of the 12 bit sign and exponent. - DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); - const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; - __ srl(at, the_int(), shift_distance); - __ or_(scratch(), scratch(), at); - __ sw(scratch(), FieldMemOperand(the_heap_number(), - HeapNumber::kExponentOffset)); - __ sll(scratch(), the_int(), 32 - shift_distance); - __ Ret(USE_DELAY_SLOT); - __ sw(scratch(), FieldMemOperand(the_heap_number(), - HeapNumber::kMantissaOffset)); - - __ bind(&max_negative_int); - // The max negative int32 is stored as a positive number in the mantissa of - // a double because it uses a sign bit instead of using two's complement. - // The actual mantissa bits stored are all 0 because the implicit most - // significant 1 bit is not stored. - non_smi_exponent += 1 << HeapNumber::kExponentShift; - __ li(scratch(), Operand(HeapNumber::kSignMask | non_smi_exponent)); - __ sw(scratch(), - FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); - __ mov(scratch(), zero_reg); - __ Ret(USE_DELAY_SLOT); - __ sw(scratch(), - FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); -} - - // Handle the case where the lhs and rhs are the same object. // Equality is almost reflexive (everything but NaN), so this is a test // for "identity and not NaN". @@ -1058,7 +998,6 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { CEntryStub::GenerateAheadOfTime(isolate); - WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); StubFailureTrampolineStub::GenerateAheadOfTime(isolate); ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
diff --git a/src/mips/code-stubs-mips.h b/src/mips/code-stubs-mips.h index afad32b..b3d2c45 100644 --- a/src/mips/code-stubs-mips.h +++ b/src/mips/code-stubs-mips.h
@@ -73,55 +73,6 @@ }; -// This stub can convert a signed int32 to a heap number (double). It does -// not work for int32s that are in Smi range! No GC occurs during this stub -// so you don't have to set up the frame. -class WriteInt32ToHeapNumberStub : public PlatformCodeStub { - public: - WriteInt32ToHeapNumberStub(Isolate* isolate, Register the_int, - Register the_heap_number, Register scratch, - Register scratch2) - : PlatformCodeStub(isolate) { - minor_key_ = IntRegisterBits::encode(the_int.code()) | - HeapNumberRegisterBits::encode(the_heap_number.code()) | - ScratchRegisterBits::encode(scratch.code()) | - SignRegisterBits::encode(scratch2.code()); - DCHECK(IntRegisterBits::is_valid(the_int.code())); - DCHECK(HeapNumberRegisterBits::is_valid(the_heap_number.code())); - DCHECK(ScratchRegisterBits::is_valid(scratch.code())); - DCHECK(SignRegisterBits::is_valid(scratch2.code())); - } - - static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); - - private: - Register the_int() const { - return Register::from_code(IntRegisterBits::decode(minor_key_)); - } - - Register the_heap_number() const { - return Register::from_code(HeapNumberRegisterBits::decode(minor_key_)); - } - - Register scratch() const { - return Register::from_code(ScratchRegisterBits::decode(minor_key_)); - } - - Register sign() const { - return Register::from_code(SignRegisterBits::decode(minor_key_)); - } - - // Minor key encoding in 16 bits. - class IntRegisterBits: public BitField<int, 0, 4> {}; - class HeapNumberRegisterBits: public BitField<int, 4, 4> {}; - class ScratchRegisterBits: public BitField<int, 8, 4> {}; - class SignRegisterBits: public BitField<int, 12, 4> {}; - - DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); - DEFINE_PLATFORM_CODE_STUB(WriteInt32ToHeapNumber, PlatformCodeStub); -}; - - class RecordWriteStub: public PlatformCodeStub { public: RecordWriteStub(Isolate* isolate,
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index c9e3686..07f32de 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc
@@ -2858,6 +2858,7 @@ __ Addu(sp, sp, Operand(sp_delta)); } } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register reg = ToRegister(instr->parameter_count()); // The argument count parameter is a smi __ SmiUntag(reg);
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc index 8f39d02..481fb8c 100644 --- a/src/mips64/code-stubs-mips64.cc +++ b/src/mips64/code-stubs-mips64.cc
@@ -268,66 +268,6 @@ } -void WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime( - Isolate* isolate) { - WriteInt32ToHeapNumberStub stub1(isolate, a1, v0, a2, a3); - WriteInt32ToHeapNumberStub stub2(isolate, a2, v0, a3, a0); - stub1.GetCode(); - stub2.GetCode(); -} - - -// See comment for class, this does NOT work for int32's that are in Smi range. -void WriteInt32ToHeapNumberStub::Generate(MacroAssembler* masm) { - Label max_negative_int; - // the_int_ has the answer which is a signed int32 but not a Smi. - // We test for the special value that has a different exponent. - STATIC_ASSERT(HeapNumber::kSignMask == 0x80000000u); - // Test sign, and save for later conditionals. - __ And(sign(), the_int(), Operand(0x80000000u)); - __ Branch(&max_negative_int, eq, the_int(), Operand(0x80000000u)); - - // Set up the correct exponent in scratch_. All non-Smi int32s have the same. - // A non-Smi integer is 1.xxx * 2^30 so the exponent is 30 (biased). - uint32_t non_smi_exponent = - (HeapNumber::kExponentBias + 30) << HeapNumber::kExponentShift; - __ li(scratch(), Operand(non_smi_exponent)); - // Set the sign bit in scratch_ if the value was negative. - __ or_(scratch(), scratch(), sign()); - // Subtract from 0 if the value was negative. - __ subu(at, zero_reg, the_int()); - __ Movn(the_int(), at, sign()); - // We should be masking the implict first digit of the mantissa away here, - // but it just ends up combining harmlessly with the last digit of the - // exponent that happens to be 1. The sign bit is 0 so we shift 10 to get - // the most significant 1 to hit the last bit of the 12 bit sign and exponent. - DCHECK(((1 << HeapNumber::kExponentShift) & non_smi_exponent) != 0); - const int shift_distance = HeapNumber::kNonMantissaBitsInTopWord - 2; - __ srl(at, the_int(), shift_distance); - __ or_(scratch(), scratch(), at); - __ sw(scratch(), FieldMemOperand(the_heap_number(), - HeapNumber::kExponentOffset)); - __ sll(scratch(), the_int(), 32 - shift_distance); - __ Ret(USE_DELAY_SLOT); - __ sw(scratch(), FieldMemOperand(the_heap_number(), - HeapNumber::kMantissaOffset)); - - __ bind(&max_negative_int); - // The max negative int32 is stored as a positive number in the mantissa of - // a double because it uses a sign bit instead of using two's complement. - // The actual mantissa bits stored are all 0 because the implicit most - // significant 1 bit is not stored. - non_smi_exponent += 1 << HeapNumber::kExponentShift; - __ li(scratch(), Operand(HeapNumber::kSignMask | non_smi_exponent)); - __ sw(scratch(), - FieldMemOperand(the_heap_number(), HeapNumber::kExponentOffset)); - __ mov(scratch(), zero_reg); - __ Ret(USE_DELAY_SLOT); - __ sw(scratch(), - FieldMemOperand(the_heap_number(), HeapNumber::kMantissaOffset)); -} - - // Handle the case where the lhs and rhs are the same object. // Equality is almost reflexive (everything but NaN), so this is a test // for "identity and not NaN". @@ -1053,7 +993,6 @@ void CodeStub::GenerateStubsAheadOfTime(Isolate* isolate) { CEntryStub::GenerateAheadOfTime(isolate); - WriteInt32ToHeapNumberStub::GenerateFixedRegStubsAheadOfTime(isolate); StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(isolate); StubFailureTrampolineStub::GenerateAheadOfTime(isolate); ArrayConstructorStubBase::GenerateStubsAheadOfTime(isolate);
diff --git a/src/mips64/code-stubs-mips64.h b/src/mips64/code-stubs-mips64.h index 6c324bb..3cd6ed6 100644 --- a/src/mips64/code-stubs-mips64.h +++ b/src/mips64/code-stubs-mips64.h
@@ -73,56 +73,6 @@ DEFINE_PLATFORM_CODE_STUB(RestoreRegistersState, PlatformCodeStub); }; -// This stub can convert a signed int32 to a heap number (double). It does -// not work for int32s that are in Smi range! No GC occurs during this stub -// so you don't have to set up the frame. -class WriteInt32ToHeapNumberStub : public PlatformCodeStub { - public: - WriteInt32ToHeapNumberStub(Isolate* isolate, Register the_int, - Register the_heap_number, Register scratch, - Register scratch2) - : PlatformCodeStub(isolate) { - minor_key_ = IntRegisterBits::encode(the_int.code()) | - HeapNumberRegisterBits::encode(the_heap_number.code()) | - ScratchRegisterBits::encode(scratch.code()) | - SignRegisterBits::encode(scratch2.code()); - DCHECK(IntRegisterBits::is_valid(the_int.code())); - DCHECK(HeapNumberRegisterBits::is_valid(the_heap_number.code())); - DCHECK(ScratchRegisterBits::is_valid(scratch.code())); - DCHECK(SignRegisterBits::is_valid(scratch2.code())); - } - - static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate); - - private: - void Generate(MacroAssembler* masm); - - Register the_int() const { - return Register::from_code(IntRegisterBits::decode(minor_key_)); - } - - Register the_heap_number() const { - return Register::from_code(HeapNumberRegisterBits::decode(minor_key_)); - } - - Register scratch() const { - return Register::from_code(ScratchRegisterBits::decode(minor_key_)); - } - - Register sign() const { - return Register::from_code(SignRegisterBits::decode(minor_key_)); - } - - // Minor key encoding in 16 bits. - class IntRegisterBits: public BitField<int, 0, 4> {}; - class HeapNumberRegisterBits: public BitField<int, 4, 4> {}; - class ScratchRegisterBits: public BitField<int, 8, 4> {}; - class SignRegisterBits: public BitField<int, 12, 4> {}; - - DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR(); - DEFINE_CODE_STUB(WriteInt32ToHeapNumber, PlatformCodeStub); -}; - class RecordWriteStub: public PlatformCodeStub { public:
diff --git a/src/mips64/lithium-codegen-mips64.cc b/src/mips64/lithium-codegen-mips64.cc index 88f6b18..35839e6 100644 --- a/src/mips64/lithium-codegen-mips64.cc +++ b/src/mips64/lithium-codegen-mips64.cc
@@ -2828,6 +2828,7 @@ __ Daddu(sp, sp, Operand(sp_delta)); } } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register reg = ToRegister(instr->parameter_count()); // The argument count parameter is a smi __ SmiUntag(reg);
diff --git a/src/objects-inl.h b/src/objects-inl.h index 40ce81a..9564ff0 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h
@@ -479,11 +479,6 @@ } -Handle<Object> MapCacheShape::AsHandle(Isolate* isolate, HashTableKey* key) { - return key->AsHandle(isolate); -} - - Handle<Object> CompilationCacheShape::AsHandle(Isolate* isolate, HashTableKey* key) { return key->AsHandle(isolate); @@ -3288,7 +3283,6 @@ CAST_ACCESSOR(JSWeakMap) CAST_ACCESSOR(JSWeakSet) CAST_ACCESSOR(Map) -CAST_ACCESSOR(MapCache) CAST_ACCESSOR(Name) CAST_ACCESSOR(NameDictionary) CAST_ACCESSOR(NormalizedMapCache)
diff --git a/src/objects.cc b/src/objects.cc index 2b5b567..ab13412 100644 --- a/src/objects.cc +++ b/src/objects.cc
@@ -14207,8 +14207,6 @@ CompilationCacheShape, HashTableKey*>; -template class HashTable<MapCache, MapCacheShape, HashTableKey*>; - template class HashTable<ObjectHashTable, ObjectHashTableShape, Handle<Object> >; @@ -15158,28 +15156,6 @@ }; -Object* MapCache::Lookup(FixedArray* array) { - DisallowHeapAllocation no_alloc; - StringsKey key(handle(array)); - int entry = FindEntry(&key); - if (entry == kNotFound) return GetHeap()->undefined_value(); - return get(EntryToIndex(entry) + 1); -} - - -Handle<MapCache> MapCache::Put( - Handle<MapCache> map_cache, Handle<FixedArray> array, Handle<Map> value) { - StringsKey key(array); - - Handle<MapCache> new_cache = EnsureCapacity(map_cache, 1, &key); - int entry = new_cache->FindInsertionEntry(key.Hash()); - new_cache->set(EntryToIndex(entry), *array); - new_cache->set(EntryToIndex(entry) + 1, *value); - new_cache->ElementAdded(); - return new_cache; -} - - template<typename Derived, typename Shape, typename Key> Handle<Derived> Dictionary<Derived, Shape, Key>::New( Isolate* isolate,
diff --git a/src/objects.h b/src/objects.h index 31d0a16..d025b24 100644 --- a/src/objects.h +++ b/src/objects.h
@@ -3462,44 +3462,6 @@ }; -class MapCacheShape : public BaseShape<HashTableKey*> { - public: - static inline bool IsMatch(HashTableKey* key, Object* value) { - return key->IsMatch(value); - } - - static inline uint32_t Hash(HashTableKey* key) { - return key->Hash(); - } - - static inline uint32_t HashForObject(HashTableKey* key, Object* object) { - return key->HashForObject(object); - } - - static inline Handle<Object> AsHandle(Isolate* isolate, HashTableKey* key); - - static const int kPrefixSize = 0; - static const int kEntrySize = 2; -}; - - -// MapCache. -// -// Maps keys that are a fixed array of unique names to a map. -// Used for canonicalize maps for object literals. -class MapCache: public HashTable<MapCache, MapCacheShape, HashTableKey*> { - public: - // Find cached value for a name key, otherwise return null. - Object* Lookup(FixedArray* key); - static Handle<MapCache> Put( - Handle<MapCache> map_cache, Handle<FixedArray> key, Handle<Map> value); - DECLARE_CAST(MapCache) - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(MapCache); -}; - - template <typename Derived, typename Shape, typename Key> class Dictionary: public HashTable<Derived, Shape, Key> { protected:
diff --git a/src/runtime/runtime-literals.cc b/src/runtime/runtime-literals.cc index c6efd02..8bbe0ee 100644 --- a/src/runtime/runtime-literals.cc +++ b/src/runtime/runtime-literals.cc
@@ -17,53 +17,22 @@ static Handle<Map> ComputeObjectLiteralMap( Handle<Context> context, Handle<FixedArray> constant_properties, bool* is_result_from_cache) { - Isolate* isolate = context->GetIsolate(); int properties_length = constant_properties->length(); int number_of_properties = properties_length / 2; - // Check that there are only internal strings and array indices among keys. - int number_of_string_keys = 0; + for (int p = 0; p != properties_length; p += 2) { Object* key = constant_properties->get(p); uint32_t element_index = 0; - if (key->IsInternalizedString()) { - number_of_string_keys++; - } else if (key->ToArrayIndex(&element_index)) { + if (key->ToArrayIndex(&element_index)) { // An index key does not require space in the property backing store. number_of_properties--; - } else { - // Bail out as a non-internalized-string non-index key makes caching - // impossible. - // DCHECK to make sure that the if condition after the loop is false. - DCHECK(number_of_string_keys != number_of_properties); - break; } } - // If we only have internalized strings and array indices among keys then we - // can use the map cache in the native context. - const int kMaxKeys = 10; - if ((number_of_string_keys == number_of_properties) && - (number_of_string_keys < kMaxKeys)) { - // Create the fixed array with the key. - Handle<FixedArray> keys = - isolate->factory()->NewFixedArray(number_of_string_keys); - if (number_of_string_keys > 0) { - int index = 0; - for (int p = 0; p < properties_length; p += 2) { - Object* key = constant_properties->get(p); - if (key->IsInternalizedString()) { - keys->set(index++, key); - } - } - DCHECK(index == number_of_string_keys); - } - *is_result_from_cache = true; - return isolate->factory()->ObjectLiteralMapFromCache(context, keys); - } - *is_result_from_cache = false; - return Map::Create(isolate, number_of_properties); + Isolate* isolate = context->GetIsolate(); + return isolate->factory()->ObjectLiteralMapFromCache( + context, number_of_properties, is_result_from_cache); } - MUST_USE_RESULT static MaybeHandle<Object> CreateLiteralBoilerplate( Isolate* isolate, Handle<FixedArray> literals, Handle<FixedArray> constant_properties); @@ -169,7 +138,6 @@ boilerplate->map()->unused_property_fields(), "FastLiteral"); } - return boilerplate; }
diff --git a/src/version.cc b/src/version.cc index 6136739..fdcb4fd 100644 --- a/src/version.cc +++ b/src/version.cc
@@ -34,7 +34,7 @@ // system so their names cannot be changed without changing the scripts. #define MAJOR_VERSION 3 #define MINOR_VERSION 31 -#define BUILD_NUMBER 0 +#define BUILD_NUMBER 1 #define PATCH_LEVEL 0 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.)
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 7e482ee..8ec1af5 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc
@@ -2822,6 +2822,7 @@ __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, rcx); } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register reg = ToRegister(instr->parameter_count()); // The argument count parameter is a smi __ SmiToInteger32(reg, reg);
diff --git a/src/x87/lithium-codegen-x87.cc b/src/x87/lithium-codegen-x87.cc index 284a666..2b6c265 100644 --- a/src/x87/lithium-codegen-x87.cc +++ b/src/x87/lithium-codegen-x87.cc
@@ -3050,6 +3050,7 @@ } __ Ret((parameter_count + extra_value_count) * kPointerSize, ecx); } else { + DCHECK(info()->IsStub()); // Functions would need to drop one more value. Register reg = ToRegister(instr->parameter_count()); // The argument count parameter is a smi __ SmiUntag(reg);
diff --git a/test/cctest/compiler/graph-builder-tester.h b/test/cctest/compiler/graph-builder-tester.h index 1bc5be7..772de4d 100644 --- a/test/cctest/compiler/graph-builder-tester.h +++ b/test/cctest/compiler/graph-builder-tester.h
@@ -61,6 +61,7 @@ explicit GraphAndBuilders(Zone* zone) : main_graph_(new (zone) Graph(zone)), main_common_(zone), + main_machine_(zone), main_simplified_(zone) {} protected:
diff --git a/test/cctest/compiler/test-instruction.cc b/test/cctest/compiler/test-instruction.cc index 425a46c..3e2b857 100644 --- a/test/cctest/compiler/test-instruction.cc +++ b/test/cctest/compiler/test-instruction.cc
@@ -33,6 +33,7 @@ info(static_cast<HydrogenCodeStub*>(NULL), main_isolate()), linkage(zone(), &info), common(zone()), + machine(zone()), code(NULL) {} ~InstructionTester() { delete code; }
diff --git a/test/cctest/compiler/test-js-constant-cache.cc b/test/cctest/compiler/test-js-constant-cache.cc index 2a591c1..8588f66 100644 --- a/test/cctest/compiler/test-js-constant-cache.cc +++ b/test/cctest/compiler/test-js-constant-cache.cc
@@ -22,7 +22,7 @@ main_common_(zone), main_javascript_(zone), main_typer_(&main_graph_, MaybeHandle<Context>()), - main_machine_() {} + main_machine_(zone) {} Graph main_graph_; CommonOperatorBuilder main_common_; JSOperatorBuilder main_javascript_;
diff --git a/test/cctest/compiler/test-js-context-specialization.cc b/test/cctest/compiler/test-js-context-specialization.cc index 264fee0..f04e327 100644 --- a/test/cctest/compiler/test-js-context-specialization.cc +++ b/test/cctest/compiler/test-js-context-specialization.cc
@@ -21,7 +21,7 @@ : DirectGraphBuilder(new (main_zone()) Graph(main_zone())), common_(main_zone()), javascript_(main_zone()), - machine_(), + machine_(main_zone()), simplified_(main_zone()), jsgraph_(graph(), common(), &javascript_, &machine_), info_(main_isolate(), main_zone()) {}
diff --git a/test/cctest/compiler/test-js-typed-lowering.cc b/test/cctest/compiler/test-js-typed-lowering.cc index 28cc90a..7c04cf3 100644 --- a/test/cctest/compiler/test-js-typed-lowering.cc +++ b/test/cctest/compiler/test-js-typed-lowering.cc
@@ -21,6 +21,7 @@ binop(NULL), unop(NULL), javascript(main_zone()), + machine(main_zone()), simplified(main_zone()), common(main_zone()), graph(main_zone()),
diff --git a/test/cctest/compiler/test-machine-operator-reducer.cc b/test/cctest/compiler/test-machine-operator-reducer.cc index 115967a..ec14cd2 100644 --- a/test/cctest/compiler/test-machine-operator-reducer.cc +++ b/test/cctest/compiler/test-machine-operator-reducer.cc
@@ -56,6 +56,7 @@ : isolate(main_isolate()), binop(NULL), unop(NULL), + machine(main_zone()), common(main_zone()), graph(main_zone()), javascript(main_zone()),
diff --git a/test/cctest/compiler/test-schedule.cc b/test/cctest/compiler/test-schedule.cc index 7b4f975..d2a52c7 100644 --- a/test/cctest/compiler/test-schedule.cc +++ b/test/cctest/compiler/test-schedule.cc
@@ -163,7 +163,8 @@ Schedule schedule(scope.main_zone()); Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); - MachineOperatorBuilder machine; + // TODO(titzer): use test operators. + MachineOperatorBuilder machine(scope.main_zone()); Node* start = graph.NewNode(common.Start(0)); graph.SetStart(start);
diff --git a/test/cctest/compiler/test-scheduler.cc b/test/cctest/compiler/test-scheduler.cc index 659aacd..f835265 100644 --- a/test/cctest/compiler/test-scheduler.cc +++ b/test/cctest/compiler/test-scheduler.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "src/v8.h" -#include "test/cctest/cctest.h" #include "src/compiler/access-builder.h" #include "src/compiler/common-operator.h" @@ -12,17 +11,21 @@ #include "src/compiler/graph.h" #include "src/compiler/graph-visualizer.h" #include "src/compiler/js-operator.h" -#include "src/compiler/machine-operator.h" #include "src/compiler/node.h" +#include "src/compiler/opcodes.h" #include "src/compiler/operator.h" #include "src/compiler/schedule.h" #include "src/compiler/scheduler.h" #include "src/compiler/simplified-operator.h" #include "src/compiler/verifier.h" +#include "test/cctest/cctest.h" using namespace v8::internal; using namespace v8::internal::compiler; +Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, 0, 1, + 0, 0); + // TODO(titzer): pull RPO tests out to their own file. static void CheckRPONumbers(BasicBlockVector* order, size_t expected, bool loops_allowed) { @@ -1571,7 +1574,6 @@ Graph graph(scope.main_zone()); CommonOperatorBuilder common_builder(scope.main_zone()); JSOperatorBuilder js_builder(scope.main_zone()); - MachineOperatorBuilder machine_builder; const Operator* op; Handle<HeapObject> object = @@ -1607,7 +1609,7 @@ Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n20); n20->ReplaceInput(0, n9); - op = machine_builder.Int32Add(); + op = &kIntAdd; Node* n19 = graph.NewNode(op, nil, nil); USE(n19); op = common_builder.Phi(kMachAnyTagged, 2); @@ -1731,7 +1733,6 @@ HandleAndZoneScope scope; Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start); @@ -1740,7 +1741,7 @@ Node* p1 = graph.NewNode(common.Parameter(1), start); Node* d1 = CreateDiamond(&graph, &common, p0); Node* d2 = CreateDiamond(&graph, &common, p1); - Node* add = graph.NewNode(machine.Int32Add(), d1, d2); + Node* add = graph.NewNode(&kIntAdd, d1, d2); Node* ret = graph.NewNode(common.Return(), add, start, start); Node* end = graph.NewNode(common.End(), ret, start); @@ -1754,7 +1755,6 @@ HandleAndZoneScope scope; Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start); @@ -1763,7 +1763,7 @@ Node* p1 = graph.NewNode(common.Parameter(1), start); Node* d1 = CreateDiamond(&graph, &common, p0); Node* d2 = CreateDiamond(&graph, &common, p1); - Node* add = graph.NewNode(machine.Int32Add(), d1, d2); + Node* add = graph.NewNode(&kIntAdd, d1, d2); Node* d3 = CreateDiamond(&graph, &common, add); Node* ret = graph.NewNode(common.Return(), d3, start, start); Node* end = graph.NewNode(common.End(), ret, start); @@ -1779,7 +1779,6 @@ Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); SimplifiedOperatorBuilder simplified(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start); @@ -1821,7 +1820,6 @@ Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); SimplifiedOperatorBuilder simplified(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start); @@ -1837,7 +1835,7 @@ Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); // TODO(mstarzinger): Make scheduler deal with non-empty loops here. - // Node* add = graph.NewNode(machine.IntAdd(), ind, fv); + // Node* add = graph.NewNode(&kIntAdd, ind, fv); Node* br1 = graph.NewNode(common.Branch(), ind, loop); Node* t1 = graph.NewNode(common.IfTrue(), br1); @@ -1863,7 +1861,6 @@ Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); SimplifiedOperatorBuilder simplified(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start); @@ -1873,7 +1870,7 @@ Node* c = graph.NewNode(common.Int32Constant(7)); Node* loop = graph.NewNode(common.Loop(2), start, start); Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); - Node* add = graph.NewNode(machine.IntAdd(), ind, c); + Node* add = graph.NewNode(&kIntAdd, ind, c); Node* br = graph.NewNode(common.Branch(), add, loop); Node* t = graph.NewNode(common.IfTrue(), br); @@ -1902,7 +1899,6 @@ Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); SimplifiedOperatorBuilder simplified(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start); @@ -1919,7 +1915,7 @@ Node* m1 = graph.NewNode(common.Merge(2), t1, f1); Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind, m1); - Node* add = graph.NewNode(machine.IntAdd(), ind, phi1); + Node* add = graph.NewNode(&kIntAdd, ind, phi1); Node* br = graph.NewNode(common.Branch(), add, loop); Node* t = graph.NewNode(common.IfTrue(), br); @@ -1942,7 +1938,6 @@ Graph graph(scope.main_zone()); CommonOperatorBuilder common(scope.main_zone()); SimplifiedOperatorBuilder simplified(scope.main_zone()); - MachineOperatorBuilder machine; Node* start = graph.NewNode(common.Start(2)); graph.SetStart(start);
diff --git a/test/cctest/compiler/test-simplified-lowering.cc b/test/cctest/compiler/test-simplified-lowering.cc index 5ddc10d..7fe4933 100644 --- a/test/cctest/compiler/test-simplified-lowering.cc +++ b/test/cctest/compiler/test-simplified-lowering.cc
@@ -744,6 +744,17 @@ } } + Node* ExampleWithTypeAndRep(Type* type, MachineType mach_type) { + FieldAccess access = {kUntaggedBase, 0, Handle<Name>::null(), type, + mach_type}; + // TODO(titzer): using loads here just to force the representation is ugly. + Node* node = graph()->NewNode(simplified()->LoadField(access), + jsgraph.IntPtrConstant(0), graph()->start(), + graph()->start()); + NodeProperties::SetBounds(node, Bounds(type)); + return node; + } + Node* Use(Node* node, MachineType type) { if (type & kTypeInt32) { return graph()->NewNode(machine()->Int32LessThan(), node, @@ -757,6 +768,9 @@ } else if (type & kRepWord64) { return graph()->NewNode(machine()->Int64LessThan(), node, Int64Constant(1)); + } else if (type & kRepWord32) { + return graph()->NewNode(machine()->Word32Equal(), node, + jsgraph.Int32Constant(1)); } else { return graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), node, jsgraph.TrueConstant()); @@ -1060,9 +1074,7 @@ TEST(LowerNumberToInt32_to_TruncateFloat64ToInt32) { // NumberToInt32(x: kRepFloat64) used as kMachInt32 TestingGraph t(Type::Number()); - Node* p0 = t.ExampleWithOutput(kMachFloat64); - // TODO(titzer): run the typer here, or attach machine type to param. - NodeProperties::SetBounds(p0, Bounds(Type::Number())); + Node* p0 = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64); Node* trunc = t.graph()->NewNode(t.simplified()->NumberToInt32(), p0); Node* use = t.Use(trunc, kMachInt32); t.Return(use); @@ -1086,17 +1098,6 @@ } -TEST(LowerNumberToInt32_to_ChangeFloat64ToTagged) { - // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepTagged -} - - -TEST(LowerNumberToInt32_to_ChangeFloat64ToInt32) { - // TODO(titzer): NumberToInt32(x: kRepFloat64 | kTypeInt32) used as kRepWord32 - // | kTypeInt32 -} - - TEST(LowerNumberToUint32_to_nop) { // NumberToUint32(x: kRepTagged | kTypeUint32) used as kRepTagged TestingGraph t(Type::Unsigned32()); @@ -1159,20 +1160,67 @@ } -TEST(LowerNumberToUint32_to_ChangeFloat64ToTagged) { - // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as - // kRepTagged +TEST(LowerNumberToUint32_to_TruncateFloat64ToInt32_uint32) { + // NumberToUint32(x: kRepFloat64) used as kRepWord32 + TestingGraph t(Type::Unsigned32()); + Node* input = t.ExampleWithTypeAndRep(Type::Number(), kMachFloat64); + Node* trunc = t.graph()->NewNode(t.simplified()->NumberToUint32(), input); + Node* use = t.Use(trunc, kRepWord32); + t.Return(use); + t.Lower(); + CheckChangeOf(IrOpcode::kTruncateFloat64ToInt32, input, use->InputAt(0)); } -TEST(LowerNumberToUint32_to_ChangeFloat64ToUint32) { - // TODO(titzer): NumberToUint32(x: kRepFloat64 | kTypeUint32) used as - // kRepWord32 +TEST(LowerNumberToUI32_of_Float64_used_as_word32) { + // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as + // kType(Int,Uint)32 | kRepWord32 + Type* types[] = {Type::Signed32(), Type::Unsigned32()}; + MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone}; + + for (int i = 0; i < 2; i++) { + for (int u = 0; u < 3; u++) { + TestingGraph t(types[i]); + Node* input = t.ExampleWithTypeAndRep( + types[i], static_cast<MachineType>(kRepFloat64 | mach[i])); + const Operator* op = i == 0 ? t.simplified()->NumberToInt32() + : t.simplified()->NumberToUint32(); + Node* trunc = t.graph()->NewNode(op, input); + Node* use = t.Use(trunc, static_cast<MachineType>(kRepWord32 | mach[u])); + t.Return(use); + t.Lower(); + IrOpcode::Value opcode = i == 0 ? IrOpcode::kChangeFloat64ToInt32 + : IrOpcode::kChangeFloat64ToUint32; + CheckChangeOf(opcode, input, use->InputAt(0)); + } + } } -TEST(LowerNumberToUint32_to_TruncateFloat64ToUint32) { - // TODO(titzer): NumberToUint32(x: kRepFloat64) used as kRepWord32 +TEST(LowerNumberToUI32_of_Float64_used_as_tagged) { + // NumberTo(Int,Uint)32(x: kRepFloat64 | kType(Int,Uint)32) used as + // kType(Int,Uint)32 | kRepTagged + Type* types[] = {Type::Signed32(), Type::Unsigned32(), Type::Any()}; + MachineType mach[] = {kTypeInt32, kTypeUint32, kMachNone}; + + for (int i = 0; i < 2; i++) { + for (int u = 0; u < 3; u++) { + TestingGraph t(types[i]); + Node* input = t.ExampleWithTypeAndRep( + types[i], static_cast<MachineType>(kRepFloat64 | mach[i])); + const Operator* op = i == 0 ? t.simplified()->NumberToInt32() + : t.simplified()->NumberToUint32(); + Node* trunc = t.graph()->NewNode(op, input); + // TODO(titzer): we use the store here to force the representation. + FieldAccess access = {kTaggedBase, 0, Handle<Name>(), types[u], + static_cast<MachineType>(mach[u] | kRepTagged)}; + Node* store = t.graph()->NewNode(t.simplified()->StoreField(access), t.p0, + trunc, t.start, t.start); + t.Effect(store); + t.Lower(); + CheckChangeOf(IrOpcode::kChangeFloat64ToTagged, input, store->InputAt(2)); + } + } }
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 5fa2a2f..d4fbb04 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc
@@ -21211,29 +21211,40 @@ } +static int CountLiveMapsInMapCache(i::Context* context) { + i::FixedArray* map_cache = i::FixedArray::cast(context->map_cache()); + int length = map_cache->length(); + int count = 0; + for (int i = 0; i < length; i++) { + i::Object* value = map_cache->get(i); + if (value->IsWeakCell() && !i::WeakCell::cast(value)->cleared()) count++; + } + return count; +} + + THREADED_TEST(Regress1516) { LocalContext context; v8::HandleScope scope(context->GetIsolate()); + // Object with 20 properties is not a common case, so it should be removed + // from the cache after GC. { v8::HandleScope temp_scope(context->GetIsolate()); - CompileRun("({'a': 0})"); + CompileRun( + "({" + "'a00': 0, 'a01': 0, 'a02': 0, 'a03': 0, 'a04': 0, " + "'a05': 0, 'a06': 0, 'a07': 0, 'a08': 0, 'a09': 0, " + "'a10': 0, 'a11': 0, 'a12': 0, 'a13': 0, 'a14': 0, " + "'a15': 0, 'a16': 0, 'a17': 0, 'a18': 0, 'a19': 0, " + "})"); } - int elements; - { i::MapCache* map_cache = - i::MapCache::cast(CcTest::i_isolate()->context()->map_cache()); - elements = map_cache->NumberOfElements(); - CHECK_LE(1, elements); - } + int elements = CountLiveMapsInMapCache(CcTest::i_isolate()->context()); + CHECK_LE(1, elements); - CcTest::heap()->CollectAllGarbage( - i::Heap::kAbortIncrementalMarkingMask); - { i::Object* raw_map_cache = CcTest::i_isolate()->context()->map_cache(); - if (raw_map_cache != CcTest::heap()->undefined_value()) { - i::MapCache* map_cache = i::MapCache::cast(raw_map_cache); - CHECK_GT(elements, map_cache->NumberOfElements()); - } - } + CcTest::heap()->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask); + + CHECK_GT(elements, CountLiveMapsInMapCache(CcTest::i_isolate()->context())); }
diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc index 0c13a68..9ebaeec 100644 --- a/test/cctest/test-decls.cc +++ b/test/cctest/test-decls.cc
@@ -683,33 +683,177 @@ TEST(CrossScriptReferencesHarmony) { - i::FLAG_use_strict = true; i::FLAG_harmony_scoping = true; i::FLAG_harmony_modules = true; v8::Isolate* isolate = CcTest::isolate(); HandleScope scope(isolate); + // Check that simple cross-script global scope access works. const char* decs[] = { - "var x = 1; x", "x", "this.x", - "function x() { return 1 }; x()", "x()", "this.x()", - "let x = 1; x", "x", "this.x", - "const x = 1; x", "x", "this.x", - "module x { export let a = 1 }; x.a", "x.a", "this.x.a", + "'use strict'; var x = 1; x", "x", + "'use strict'; function x() { return 1 }; x()", "x()", + "'use strict'; let x = 1; x", "x", + "'use strict'; const x = 1; x", "x", + "'use strict'; module x { export let a = 1 }; x.a", "x.a", NULL }; - for (int i = 0; decs[i] != NULL; i += 3) { + for (int i = 0; decs[i] != NULL; i += 2) { SimpleContext context; context.Check(decs[i], EXPECT_RESULT, Number::New(isolate, 1)); context.Check(decs[i+1], EXPECT_RESULT, Number::New(isolate, 1)); - // TODO(rossberg): The current ES6 draft spec does not reflect lexical - // bindings on the global object. However, this will probably change, in - // which case we reactivate the following test. - if (i/3 < 2) { - context.Check(decs[i+2], EXPECT_RESULT, Number::New(isolate, 1)); - } } + + // Check that cross-script global scope access works with late declarations. + { + SimpleContext context; + context.Check("function d0() { return x0 }", // dynamic lookup + EXPECT_RESULT, Undefined(isolate)); + context.Check("this.x0 = -1;" + "d0()", + EXPECT_RESULT, Number::New(isolate, -1)); + context.Check("'use strict';" + "function f0() { let y = 10; return x0 + y }" + "function g0() { let y = 10; return eval('x0 + y') }" + "function h0() { let y = 10; return (1,eval)('x0') + y }" + "x0 + f0() + g0() + h0()", + EXPECT_RESULT, Number::New(isolate, 26)); + + context.Check("'use strict';" + "let x1 = 1;" + "function f1() { let y = 10; return x1 + y }" + "function g1() { let y = 10; return eval('x1 + y') }" + "function h1() { let y = 10; return (1,eval)('x1') + y }" + "function i1() { " + " let y = 10; return (typeof x2 === 'undefined' ? 0 : 2) + y" + "}" + "function j1() { let y = 10; return eval('x2 + y') }" + "function k1() { let y = 10; return (1,eval)('x2') + y }" + "function cl() { " + " let y = 10; " + " return { " + " f: function(){ return x1 + y }," + " g: function(){ return eval('x1 + y') }," + " h: function(){ return (1,eval)('x1') + y }," + " i: function(){" + " return (typeof x2 == 'undefined' ? 0 : 2) + y" + " }," + " j: function(){ return eval('x2 + y') }," + " k: function(){ return (1,eval)('x2') + y }," + " }" + "}" + "let o = cl();" + "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();", + EXPECT_RESULT, Number::New(isolate, 36)); + context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();", + EXPECT_RESULT, Number::New(isolate, 36)); + context.Check("o.f() + o.g() + o.h();", + EXPECT_RESULT, Number::New(isolate, 33)); + context.Check("i1() + o.i();", + EXPECT_RESULT, Number::New(isolate, 20)); + + context.Check("'use strict';" + "let x2 = 2;" + "function f2() { let y = 20; return x2 + y }" + "function g2() { let y = 20; return eval('x2 + y') }" + "function h2() { let y = 20; return (1,eval)('x2') + y }" + "function i2() { let y = 20; return x1 + y }" + "function j2() { let y = 20; return eval('x1 + y') }" + "function k2() { let y = 20; return (1,eval)('x1') + y }" + "x2 + eval('x2') + (1,eval)('x2') + f2() + g2() + h2();", + EXPECT_RESULT, Number::New(isolate, 72)); + context.Check("x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();", + EXPECT_RESULT, Number::New(isolate, 36)); + context.Check("i1() + j1() + k1();", + EXPECT_RESULT, Number::New(isolate, 36)); + context.Check("i2() + j2() + k2();", + EXPECT_RESULT, Number::New(isolate, 63)); + context.Check("o.f() + o.g() + o.h();", + EXPECT_RESULT, Number::New(isolate, 33)); + context.Check("o.i() + o.j() + o.k();", + EXPECT_RESULT, Number::New(isolate, 36)); + context.Check("i1() + o.i();", + EXPECT_RESULT, Number::New(isolate, 24)); + + context.Check("'use strict';" + "let x0 = 100;" + "x0 + eval('x0') + (1,eval)('x0') + " + " d0() + f0() + g0() + h0();", + EXPECT_RESULT, Number::New(isolate, 730)); + context.Check("x0 + eval('x0') + (1,eval)('x0') + " + " d0() + f0() + g0() + h0();", + EXPECT_RESULT, Number::New(isolate, 730)); + context.Check("delete this.x0;" + "x0 + eval('x0') + (1,eval)('x0') + " + " d0() + f0() + g0() + h0();", + EXPECT_RESULT, Number::New(isolate, 730)); + context.Check("this.x1 = 666;" + "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();", + EXPECT_RESULT, Number::New(isolate, 36)); + context.Check("delete this.x1;" + "x1 + eval('x1') + (1,eval)('x1') + f1() + g1() + h1();", + EXPECT_RESULT, Number::New(isolate, 36)); + } + + // Check that caching does respect scopes. + { + SimpleContext context; + const char* script1 = "(function(){ return y1 })()"; + const char* script2 = "(function(){ return y2 })()"; + + context.Check(script1, EXPECT_EXCEPTION); + context.Check("this.y1 = 1; this.y2 = 2; 0;", + EXPECT_RESULT, Number::New(isolate, 0)); + context.Check(script1, + EXPECT_RESULT, Number::New(isolate, 1)); + context.Check("'use strict'; let y1 = 3; 0;", + EXPECT_RESULT, Number::New(isolate, 0)); + // TODO(dslomov): still returns 1 not 3 + // context.Check(script1, + // EXPECT_RESULT, Number::New(isolate, 3)); + context.Check("y1 = 4;", + EXPECT_RESULT, Number::New(isolate, 4)); + // TODO(dslomov): still returns 1 not 4 + // context.Check(script1, + // EXPECT_RESULT, Number::New(isolate, 4)); + + context.Check(script2, + EXPECT_RESULT, Number::New(isolate, 2)); + context.Check("'use strict'; let y2 = 5; 0;", + EXPECT_RESULT, Number::New(isolate, 0)); + // TODO(dslomov): still returns 1 not 4 + // context.Check(script1, + // EXPECT_RESULT, Number::New(isolate, 4)); + // TODO(dslomov): still returns 2 not 5 + // context.Check(script2, + // EXPECT_RESULT, Number::New(isolate, 5)); + } +} + + +TEST(GlobalLexicalOSR) { + i::FLAG_use_strict = true; + i::FLAG_harmony_scoping = true; + i::FLAG_harmony_modules = true; + + v8::Isolate* isolate = CcTest::isolate(); + HandleScope scope(isolate); + SimpleContext context; + + context.Check("'use strict';" + "let x = 1; x;", + EXPECT_RESULT, Number::New(isolate, 1)); + context.Check("'use strict';" + "let y = 2*x;" + "++x;" + "let z = 0;" + "const limit = 100000;" + "for (var i = 0; i < limit; ++i) {" + " z += x + y;" + "}" + "z;", + EXPECT_RESULT, Number::New(isolate, 400000)); }
diff --git a/test/mjsunit/mod-range.js b/test/mjsunit/mod-range.js new file mode 100644 index 0000000..0cded89 --- /dev/null +++ b/test/mjsunit/mod-range.js
@@ -0,0 +1,79 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax + +function g1(i) { + var x = i * 1; + return (x >>> 0) % 1000000000000; +} + +function g2(i) { + var x = i * 1; + return ((x >>> 0) % 1000000000000) | 0; +} + +function test1() { + assertEquals(2294967296, g1(-2000000000)); + assertEquals(2294967295, g1(-2000000001)); + assertEquals(2294967290, g1(-2000000006)); + + assertEquals(2147483651, g1(-2147483645)); + assertEquals(2147483650, g1(-2147483646)); + assertEquals(2147483649, g1(-2147483647)); + assertEquals(2147483648, g1(-2147483648)); + assertEquals(2147483647, g1(-2147483649)); + + assertEquals(3000000000, g1(3000000000)); + assertEquals(3000000001, g1(3000000001)); + assertEquals(3000000002, g1(3000000002)); + + assertEquals(4000000000, g1(4000000000)); + assertEquals(4000400001, g1(4000400001)); + assertEquals(4000400002, g1(4000400002)); + + assertEquals(3, g1(4294967299)); + assertEquals(2, g1(4294967298)); + assertEquals(1, g1(4294967297)); + assertEquals(0, g1(4294967296)); + assertEquals(4294967295, g1(4294967295)); + assertEquals(4294967294, g1(4294967294)); + assertEquals(4294967293, g1(4294967293)); + assertEquals(4294967292, g1(4294967292)); +} + +%NeverOptimizeFunction(test1); +test1(); + +function test2() { + assertEquals(-2000000000, g2(-2000000000)); + assertEquals(-2000000001, g2(-2000000001)); + assertEquals(-2000000006, g2(-2000000006)); + + assertEquals(-2147483645, g2(-2147483645)); + assertEquals(-2147483646, g2(-2147483646)); + assertEquals(-2147483647, g2(-2147483647)); + assertEquals(-2147483648, g2(-2147483648)); + assertEquals(2147483647, g2(-2147483649)); + + assertEquals(-1294967296, g2(3000000000)); + assertEquals(-1294967295, g2(3000000001)); + assertEquals(-1294967294, g2(3000000002)); + + assertEquals(-294967296, g2(4000000000)); + assertEquals(-294567295, g2(4000400001)); + assertEquals(-294567294, g2(4000400002)); + + assertEquals(3, g2(4294967299)); + assertEquals(2, g2(4294967298)); + assertEquals(1, g2(4294967297)); + assertEquals(0, g2(4294967296)); + assertEquals(-1, g2(4294967295)); + assertEquals(-2, g2(4294967294)); + assertEquals(-3, g2(4294967293)); + assertEquals(-4, g2(4294967292)); +} + +%NeverOptimizeFunction(test2); +test2();
diff --git a/test/mjsunit/regress/regress-crbug-431602.js b/test/mjsunit/regress/regress-crbug-431602.js new file mode 100644 index 0000000..2467aaf --- /dev/null +++ b/test/mjsunit/regress/regress-crbug-431602.js
@@ -0,0 +1,23 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --always-opt + +var heap_number_producer = {y:1.5}; +heap_number_producer.y = 0; +var heap_number_zero = heap_number_producer.y; +var non_constant_eight = {}; +non_constant_eight = 8; + +function BreakIt() { + return heap_number_zero | (1 | non_constant_eight); +} + +function expose(a, b, c) { + return b; +} + +assertEquals(9, expose(8, 9, 10)); +assertEquals(9, expose(8, BreakIt(), 10)); +assertEquals(9, BreakIt());
diff --git a/test/unittests/compiler/change-lowering-unittest.cc b/test/unittests/compiler/change-lowering-unittest.cc index 17d6513..7f5ec8f 100644 --- a/test/unittests/compiler/change-lowering-unittest.cc +++ b/test/unittests/compiler/change-lowering-unittest.cc
@@ -66,7 +66,7 @@ } Reduction Reduce(Node* node) { - MachineOperatorBuilder machine(WordRepresentation()); + MachineOperatorBuilder machine(zone(), WordRepresentation()); JSOperatorBuilder javascript(zone()); JSGraph jsgraph(graph(), common(), &javascript, &machine); CompilationInfo info(isolate(), zone());
diff --git a/test/unittests/compiler/js-builtin-reducer-unittest.cc b/test/unittests/compiler/js-builtin-reducer-unittest.cc index 0a0d8d6..48ad1b7 100644 --- a/test/unittests/compiler/js-builtin-reducer-unittest.cc +++ b/test/unittests/compiler/js-builtin-reducer-unittest.cc
@@ -23,7 +23,7 @@ protected: Reduction Reduce(Node* node, MachineOperatorBuilder::Flags flags = MachineOperatorBuilder::Flag::kNoFlags) { - MachineOperatorBuilder machine(kMachPtr, flags); + MachineOperatorBuilder machine(zone(), kMachPtr, flags); JSGraph jsgraph(graph(), common(), javascript(), &machine); JSBuiltinReducer reducer(&jsgraph); return reducer.Reduce(node);
diff --git a/test/unittests/compiler/js-typed-lowering-unittest.cc b/test/unittests/compiler/js-typed-lowering-unittest.cc index 539785d..97ffd83 100644 --- a/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -38,7 +38,7 @@ protected: Reduction Reduce(Node* node) { - MachineOperatorBuilder machine; + MachineOperatorBuilder machine(zone()); JSGraph jsgraph(graph(), common(), javascript(), &machine); JSTypedLowering reducer(&jsgraph); return reducer.Reduce(node);
diff --git a/test/unittests/compiler/machine-operator-reducer-unittest.cc b/test/unittests/compiler/machine-operator-reducer-unittest.cc index a62216d..065a734 100644 --- a/test/unittests/compiler/machine-operator-reducer-unittest.cc +++ b/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -22,7 +22,7 @@ class MachineOperatorReducerTest : public TypedGraphTest { public: explicit MachineOperatorReducerTest(int num_parameters = 2) - : TypedGraphTest(num_parameters) {} + : TypedGraphTest(num_parameters), machine_(zone()) {} protected: Reduction Reduce(Node* node) {
diff --git a/test/unittests/compiler/node-matchers-unittest.cc b/test/unittests/compiler/node-matchers-unittest.cc index 843a44e..f087c66 100644 --- a/test/unittests/compiler/node-matchers-unittest.cc +++ b/test/unittests/compiler/node-matchers-unittest.cc
@@ -18,7 +18,7 @@ class NodeMatcherTest : public GraphTest { public: - NodeMatcherTest() {} + NodeMatcherTest() : machine_(zone()) {} virtual ~NodeMatcherTest() {} MachineOperatorBuilder* machine() { return &machine_; }
diff --git a/test/unittests/compiler/select-lowering-unittest.cc b/test/unittests/compiler/select-lowering-unittest.cc index 6dbd7ad..51efc83 100644 --- a/test/unittests/compiler/select-lowering-unittest.cc +++ b/test/unittests/compiler/select-lowering-unittest.cc
@@ -10,6 +10,7 @@ using testing::AllOf; using testing::Capture; using testing::CaptureEq; +using testing::Not; namespace v8 { namespace internal { @@ -33,12 +34,12 @@ Node* const p2 = Parameter(2); Node* const p3 = Parameter(3); Node* const p4 = Parameter(4); + Node* const s0 = graph()->NewNode(common()->Select(kMachInt32), p0, p1, p2); Capture<Node*> branch; Capture<Node*> merge; { - Reduction const r = - Reduce(graph()->NewNode(common()->Select(kMachInt32), p0, p1, p2)); + Reduction const r = Reduce(s0); ASSERT_TRUE(r.Changed()); EXPECT_THAT( r.replacement(), @@ -55,6 +56,15 @@ ASSERT_TRUE(r.Changed()); EXPECT_THAT(r.replacement(), IsPhi(kMachInt32, p3, p4, CaptureEq(&merge))); } + { + // We must not reuse the diamond if it is reachable from either else/then + // values of the Select, because the resulting graph can not be scheduled. + Reduction const r = + Reduce(graph()->NewNode(common()->Select(kMachInt32), p0, s0, p0)); + ASSERT_TRUE(r.Changed()); + EXPECT_THAT(r.replacement(), + IsPhi(kMachInt32, s0, p0, Not(CaptureEq(&merge)))); + } } } // namespace compiler
diff --git a/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/test/unittests/compiler/simplified-operator-reducer-unittest.cc index 465ee84..7f8e43d 100644 --- a/test/unittests/compiler/simplified-operator-reducer-unittest.cc +++ b/test/unittests/compiler/simplified-operator-reducer-unittest.cc
@@ -22,7 +22,7 @@ protected: Reduction Reduce(Node* node) { - MachineOperatorBuilder machine; + MachineOperatorBuilder machine(zone()); JSOperatorBuilder javascript(zone()); JSGraph jsgraph(graph(), common(), &javascript, &machine); SimplifiedOperatorReducer reducer(&jsgraph);
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp index b675e18..0ba4e5a 100644 --- a/tools/gyp/v8.gyp +++ b/tools/gyp/v8.gyp
@@ -485,6 +485,8 @@ '../../src/compiler/raw-machine-assembler.h', '../../src/compiler/register-allocator.cc', '../../src/compiler/register-allocator.h', + '../../src/compiler/register-allocator-verifier.cc', + '../../src/compiler/register-allocator-verifier.h', '../../src/compiler/register-configuration.cc', '../../src/compiler/register-configuration.h', '../../src/compiler/representation-change.h',
diff --git a/tools/push-to-trunk/common_includes.py b/tools/push-to-trunk/common_includes.py index bb040f5..a7f8047 100644 --- a/tools/push-to-trunk/common_includes.py +++ b/tools/push-to-trunk/common_includes.py
@@ -45,6 +45,7 @@ from git_recipes import GitRecipesMixin from git_recipes import GitFailedException +CHANGELOG_FILE = "ChangeLog" VERSION_FILE = os.path.join("src", "version.cc") # V8 base directory.
diff --git a/tools/push-to-trunk/push_to_trunk.py b/tools/push-to-trunk/push_to_trunk.py index 0df548b..941d041 100755 --- a/tools/push-to-trunk/push_to_trunk.py +++ b/tools/push-to-trunk/push_to_trunk.py
@@ -319,12 +319,11 @@ # The change log has been modified by the patch. Reset it to the version # on trunk and apply the exact changes determined by this PrepareChangeLog # step above. - self.GitCheckoutFile(self.Config("CHANGELOG_FILE"), - self.vc.RemoteCandidateBranch()) + self.GitCheckoutFile(CHANGELOG_FILE, self.vc.RemoteCandidateBranch()) changelog_entry = FileToText(self.Config("CHANGELOG_ENTRY_FILE")) - old_change_log = FileToText(self.Config("CHANGELOG_FILE")) + old_change_log = FileToText(os.path.join(self.default_cwd, CHANGELOG_FILE)) new_change_log = "%s\n\n\n%s" % (changelog_entry, old_change_log) - TextToFile(new_change_log, self.Config("CHANGELOG_FILE")) + TextToFile(new_change_log, os.path.join(self.default_cwd, CHANGELOG_FILE)) os.remove(self.Config("CHANGELOG_ENTRY_FILE")) @@ -423,7 +422,6 @@ "BRANCHNAME": "prepare-push", "TRUNKBRANCH": "trunk-push", "PERSISTFILE_BASENAME": "/tmp/v8-push-to-trunk-tempfile", - "CHANGELOG_FILE": "ChangeLog", "CHANGELOG_ENTRY_FILE": "/tmp/v8-push-to-trunk-tempfile-changelog-entry", "PATCH_FILE": "/tmp/v8-push-to-trunk-tempfile-patch-file", "COMMITMSG_FILE": "/tmp/v8-push-to-trunk-tempfile-commitmsg",
diff --git a/tools/push-to-trunk/test_scripts.py b/tools/push-to-trunk/test_scripts.py index 41cc97f..14eb50e 100644 --- a/tools/push-to-trunk/test_scripts.py +++ b/tools/push-to-trunk/test_scripts.py
@@ -57,7 +57,6 @@ "BRANCHNAME": "test-prepare-push", "TRUNKBRANCH": "test-trunk-push", "PERSISTFILE_BASENAME": "/tmp/test-v8-push-to-trunk-tempfile", - "CHANGELOG_FILE": None, "CHANGELOG_ENTRY_FILE": "/tmp/test-v8-push-to-trunk-tempfile-changelog-entry", "PATCH_FILE": "/tmp/test-v8-push-to-trunk-tempfile-patch", "COMMITMSG_FILE": "/tmp/test-v8-push-to-trunk-tempfile-commitmsg", @@ -717,9 +716,9 @@ self.WriteFakeVersionFile(build=5) TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile() - TEST_CONFIG["CHANGELOG_FILE"] = self.MakeEmptyTempFile() bleeding_edge_change_log = "2014-03-17: Sentinel\n" - TextToFile(bleeding_edge_change_log, TEST_CONFIG["CHANGELOG_FILE"]) + TextToFile(bleeding_edge_change_log, + os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) os.environ["EDITOR"] = "vi" def ResetChangeLog(): @@ -728,7 +727,8 @@ trunk_change_log = """1999-04-05: Version 3.22.4 Performance and stability improvements on all platforms.\n""" - TextToFile(trunk_change_log, TEST_CONFIG["CHANGELOG_FILE"]) + TextToFile(trunk_change_log, + os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) def ResetToTrunk(): ResetChangeLog() @@ -751,7 +751,8 @@ self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version)) # Check that the change log on the trunk branch got correctly modified. - change_log = FileToText(TEST_CONFIG["CHANGELOG_FILE"]) + change_log = FileToText( + os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) self.assertEquals( """1999-07-31: Version 3.22.5 @@ -815,8 +816,7 @@ Cmd(("git new-branch %s --upstream origin/candidates" % TEST_CONFIG["TRUNKBRANCH"]), "", cb=ResetToTrunk), Cmd("git apply --index --reject \"%s\"" % TEST_CONFIG["PATCH_FILE"], ""), - Cmd(("git checkout -f origin/candidates -- %s" % - TEST_CONFIG["CHANGELOG_FILE"]), "", + Cmd("git checkout -f origin/candidates -- ChangeLog", "", cb=ResetChangeLog), Cmd("git checkout -f origin/candidates -- src/version.cc", "", cb=self.WriteFakeVersionFile), @@ -846,7 +846,7 @@ else: args += ["-r", "reviewer@chromium.org"] PushToTrunk(TEST_CONFIG, self).Run(args) - cl = FileToText(TEST_CONFIG["CHANGELOG_FILE"]) + cl = FileToText(os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl)) self.assertTrue(re.search(r" Log text 1 \(issue 321\).", cl)) self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl)) @@ -873,9 +873,9 @@ self.WriteFakeVersionFile(build=5) TEST_CONFIG["CHANGELOG_ENTRY_FILE"] = self.MakeEmptyTempFile() - TEST_CONFIG["CHANGELOG_FILE"] = self.MakeEmptyTempFile() bleeding_edge_change_log = "2014-03-17: Sentinel\n" - TextToFile(bleeding_edge_change_log, TEST_CONFIG["CHANGELOG_FILE"]) + TextToFile(bleeding_edge_change_log, + os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) def ResetChangeLog(): """On 'git co -b new_branch svn/trunk', and 'git checkout -- ChangeLog', @@ -883,7 +883,8 @@ trunk_change_log = """1999-04-05: Version 3.22.4 Performance and stability improvements on all platforms.\n""" - TextToFile(trunk_change_log, TEST_CONFIG["CHANGELOG_FILE"]) + TextToFile(trunk_change_log, + os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) def ResetToTrunk(): ResetChangeLog() @@ -906,7 +907,8 @@ self.assertTrue(re.search(r"#define IS_CANDIDATE_VERSION\s+0", version)) # Check that the change log on the trunk branch got correctly modified. - change_log = FileToText(TEST_CONFIG["CHANGELOG_FILE"]) + change_log = FileToText( + os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) self.assertEquals( """1999-07-31: Version 3.22.5 @@ -949,8 +951,7 @@ Cmd(("git new-branch %s --upstream origin/candidates" % TEST_CONFIG["TRUNKBRANCH"]), "", cb=ResetToTrunk), Cmd("git apply --index --reject \"%s\"" % TEST_CONFIG["PATCH_FILE"], ""), - Cmd(("git checkout -f origin/candidates -- %s" % - TEST_CONFIG["CHANGELOG_FILE"]), "", + Cmd("git checkout -f origin/candidates -- ChangeLog", "", cb=ResetChangeLog), Cmd("git checkout -f origin/candidates -- src/version.cc", "", cb=self.WriteFakeVersionFile), @@ -989,7 +990,7 @@ "--work-dir", TEST_CONFIG["DEFAULT_CWD"]] PushToTrunk(TEST_CONFIG, self).Run(args) - cl = FileToText(TEST_CONFIG["CHANGELOG_FILE"]) + cl = FileToText(os.path.join(TEST_CONFIG["DEFAULT_CWD"], CHANGELOG_FILE)) self.assertTrue(re.search(r"^\d\d\d\d\-\d+\-\d+: Version 3\.22\.5", cl)) self.assertTrue(re.search(r" Log text 1 \(issue 321\).", cl)) self.assertTrue(re.search(r"1999\-04\-05: Version 3\.22\.4", cl))
diff --git a/tools/testrunner/local/progress.py b/tools/testrunner/local/progress.py index 8caa58c..84aceba 100644 --- a/tools/testrunner/local/progress.py +++ b/tools/testrunner/local/progress.py
@@ -333,6 +333,7 @@ "stderr": test.output.stderr, "exit_code": test.output.exit_code, "result": test.suite.GetOutcome(test), + "expected": list(test.outcomes) or ["PASS"], })