| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_PPC | 7 #if V8_TARGET_ARCH_PPC |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 Label not_identical; | 253 Label not_identical; |
| 254 Label heap_number, return_equal; | 254 Label heap_number, return_equal; |
| 255 __ cmp(r3, r4); | 255 __ cmp(r3, r4); |
| 256 __ bne(¬_identical); | 256 __ bne(¬_identical); |
| 257 | 257 |
| 258 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), | 258 // Test for NaN. Sadly, we can't just compare to Factory::nan_value(), |
| 259 // so we do the second best thing - test it ourselves. | 259 // so we do the second best thing - test it ourselves. |
| 260 // They are both equal and they are not both Smis so both of them are not | 260 // They are both equal and they are not both Smis so both of them are not |
| 261 // Smis. If it's not a heap number, then return equal. | 261 // Smis. If it's not a heap number, then return equal. |
| 262 if (cond == lt || cond == gt) { | 262 if (cond == lt || cond == gt) { |
| 263 Label not_simd; |
| 263 // Call runtime on identical JSObjects. | 264 // Call runtime on identical JSObjects. |
| 264 __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE); | 265 __ CompareObjectType(r3, r7, r7, FIRST_SPEC_OBJECT_TYPE); |
| 265 __ bge(slow); | 266 __ bge(slow); |
| 266 // Call runtime on identical symbols since we need to throw a TypeError. | 267 // Call runtime on identical symbols since we need to throw a TypeError. |
| 267 __ cmpi(r7, Operand(SYMBOL_TYPE)); | 268 __ cmpi(r7, Operand(SYMBOL_TYPE)); |
| 268 __ beq(slow); | 269 __ beq(slow); |
| 269 // Call runtime on identical SIMD values since we must throw a TypeError. | 270 // Call runtime on identical SIMD values since we must throw a TypeError. |
| 270 __ cmpi(r7, Operand(FLOAT32X4_TYPE)); | 271 __ cmpi(r7, Operand(FIRST_SIMD_VALUE_TYPE)); |
| 271 __ beq(slow); | 272 __ blt(¬_simd); |
| 273 __ cmpi(r7, Operand(LAST_SIMD_VALUE_TYPE)); |
| 274 __ ble(slow); |
| 275 __ bind(¬_simd); |
| 272 if (is_strong(strength)) { | 276 if (is_strong(strength)) { |
| 273 // Call the runtime on anything that is converted in the semantics, since | 277 // Call the runtime on anything that is converted in the semantics, since |
| 274 // we need to throw a TypeError. Smis have already been ruled out. | 278 // we need to throw a TypeError. Smis have already been ruled out. |
| 275 __ cmpi(r7, Operand(HEAP_NUMBER_TYPE)); | 279 __ cmpi(r7, Operand(HEAP_NUMBER_TYPE)); |
| 276 __ beq(&return_equal); | 280 __ beq(&return_equal); |
| 277 __ andi(r0, r7, Operand(kIsNotStringMask)); | 281 __ andi(r0, r7, Operand(kIsNotStringMask)); |
| 278 __ bne(slow, cr0); | 282 __ bne(slow, cr0); |
| 279 } | 283 } |
| 280 } else { | 284 } else { |
| 281 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); | 285 __ CompareObjectType(r3, r7, r7, HEAP_NUMBER_TYPE); |
| 282 __ beq(&heap_number); | 286 __ beq(&heap_number); |
| 283 // Comparing JS objects with <=, >= is complicated. | 287 // Comparing JS objects with <=, >= is complicated. |
| 284 if (cond != eq) { | 288 if (cond != eq) { |
| 289 Label not_simd; |
| 285 __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE)); | 290 __ cmpi(r7, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 286 __ bge(slow); | 291 __ bge(slow); |
| 287 // Call runtime on identical symbols since we need to throw a TypeError. | 292 // Call runtime on identical symbols since we need to throw a TypeError. |
| 288 __ cmpi(r7, Operand(SYMBOL_TYPE)); | 293 __ cmpi(r7, Operand(SYMBOL_TYPE)); |
| 289 __ beq(slow); | 294 __ beq(slow); |
| 290 // Call runtime on identical SIMD values since we must throw a TypeError. | 295 // Call runtime on identical SIMD values since we must throw a TypeError. |
| 291 __ cmpi(r7, Operand(FLOAT32X4_TYPE)); | 296 __ cmpi(r7, Operand(FIRST_SIMD_VALUE_TYPE)); |
| 292 __ beq(slow); | 297 __ blt(¬_simd); |
| 298 __ cmpi(r7, Operand(LAST_SIMD_VALUE_TYPE)); |
| 299 __ ble(slow); |
| 300 __ bind(¬_simd); |
| 293 if (is_strong(strength)) { | 301 if (is_strong(strength)) { |
| 294 // Call the runtime on anything that is converted in the semantics, | 302 // Call the runtime on anything that is converted in the semantics, |
| 295 // since we need to throw a TypeError. Smis and heap numbers have | 303 // since we need to throw a TypeError. Smis and heap numbers have |
| 296 // already been ruled out. | 304 // already been ruled out. |
| 297 __ andi(r0, r7, Operand(kIsNotStringMask)); | 305 __ andi(r0, r7, Operand(kIsNotStringMask)); |
| 298 __ bne(slow, cr0); | 306 __ bne(slow, cr0); |
| 299 } | 307 } |
| 300 // Normally here we fall through to return_equal, but undefined is | 308 // Normally here we fall through to return_equal, but undefined is |
| 301 // special: (undefined == undefined) == true, but | 309 // special: (undefined == undefined) == true, but |
| 302 // (undefined <= undefined) == false! See ECMAScript 11.8.5. | 310 // (undefined <= undefined) == false! See ECMAScript 11.8.5. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 __ cmpi(r3, Operand::Zero()); | 362 __ cmpi(r3, Operand::Zero()); |
| 355 // For equal we already have the right value in r3: Return zero (equal) | 363 // For equal we already have the right value in r3: Return zero (equal) |
| 356 // if all bits in mantissa are zero (it's an Infinity) and non-zero if | 364 // if all bits in mantissa are zero (it's an Infinity) and non-zero if |
| 357 // not (it's a NaN). For <= and >= we need to load r0 with the failing | 365 // not (it's a NaN). For <= and >= we need to load r0 with the failing |
| 358 // value if it's a NaN. | 366 // value if it's a NaN. |
| 359 if (cond != eq) { | 367 if (cond != eq) { |
| 360 if (CpuFeatures::IsSupported(ISELECT)) { | 368 if (CpuFeatures::IsSupported(ISELECT)) { |
| 361 __ li(r4, Operand((cond == le) ? GREATER : LESS)); | 369 __ li(r4, Operand((cond == le) ? GREATER : LESS)); |
| 362 __ isel(eq, r3, r3, r4); | 370 __ isel(eq, r3, r3, r4); |
| 363 } else { | 371 } else { |
| 372 Label not_equal; |
| 373 __ bne(¬_equal); |
| 364 // All-zero means Infinity means equal. | 374 // All-zero means Infinity means equal. |
| 365 __ Ret(eq); | 375 __ Ret(); |
| 376 __ bind(¬_equal); |
| 366 if (cond == le) { | 377 if (cond == le) { |
| 367 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. | 378 __ li(r3, Operand(GREATER)); // NaN <= NaN should fail. |
| 368 } else { | 379 } else { |
| 369 __ li(r3, Operand(LESS)); // NaN >= NaN should fail. | 380 __ li(r3, Operand(LESS)); // NaN >= NaN should fail. |
| 370 } | 381 } |
| 371 } | 382 } |
| 372 } | 383 } |
| 373 __ Ret(); | 384 __ Ret(); |
| 374 } | 385 } |
| 375 // No fall through here. | 386 // No fall through here. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 386 | 397 |
| 387 Label rhs_is_smi; | 398 Label rhs_is_smi; |
| 388 __ JumpIfSmi(rhs, &rhs_is_smi); | 399 __ JumpIfSmi(rhs, &rhs_is_smi); |
| 389 | 400 |
| 390 // Lhs is a Smi. Check whether the rhs is a heap number. | 401 // Lhs is a Smi. Check whether the rhs is a heap number. |
| 391 __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); | 402 __ CompareObjectType(rhs, r6, r7, HEAP_NUMBER_TYPE); |
| 392 if (strict) { | 403 if (strict) { |
| 393 // If rhs is not a number and lhs is a Smi then strict equality cannot | 404 // If rhs is not a number and lhs is a Smi then strict equality cannot |
| 394 // succeed. Return non-equal | 405 // succeed. Return non-equal |
| 395 // If rhs is r3 then there is already a non zero value in it. | 406 // If rhs is r3 then there is already a non zero value in it. |
| 407 Label skip; |
| 408 __ beq(&skip); |
| 396 if (!rhs.is(r3)) { | 409 if (!rhs.is(r3)) { |
| 397 Label skip; | |
| 398 __ beq(&skip); | |
| 399 __ mov(r3, Operand(NOT_EQUAL)); | 410 __ mov(r3, Operand(NOT_EQUAL)); |
| 400 __ Ret(); | |
| 401 __ bind(&skip); | |
| 402 } else { | |
| 403 __ Ret(ne); | |
| 404 } | 411 } |
| 412 __ Ret(); |
| 413 __ bind(&skip); |
| 405 } else { | 414 } else { |
| 406 // Smi compared non-strictly with a non-Smi non-heap-number. Call | 415 // Smi compared non-strictly with a non-Smi non-heap-number. Call |
| 407 // the runtime. | 416 // the runtime. |
| 408 __ bne(slow); | 417 __ bne(slow); |
| 409 } | 418 } |
| 410 | 419 |
| 411 // Lhs is a smi, rhs is a number. | 420 // Lhs is a smi, rhs is a number. |
| 412 // Convert lhs to a double in d7. | 421 // Convert lhs to a double in d7. |
| 413 __ SmiToDouble(d7, lhs); | 422 __ SmiToDouble(d7, lhs); |
| 414 // Load the double from rhs, tagged HeapNumber r3, to d6. | 423 // Load the double from rhs, tagged HeapNumber r3, to d6. |
| 415 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); | 424 __ lfd(d6, FieldMemOperand(rhs, HeapNumber::kValueOffset)); |
| 416 | 425 |
| 417 // We now have both loaded as doubles but we can skip the lhs nan check | 426 // We now have both loaded as doubles but we can skip the lhs nan check |
| 418 // since it's a smi. | 427 // since it's a smi. |
| 419 __ b(lhs_not_nan); | 428 __ b(lhs_not_nan); |
| 420 | 429 |
| 421 __ bind(&rhs_is_smi); | 430 __ bind(&rhs_is_smi); |
| 422 // Rhs is a smi. Check whether the non-smi lhs is a heap number. | 431 // Rhs is a smi. Check whether the non-smi lhs is a heap number. |
| 423 __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); | 432 __ CompareObjectType(lhs, r7, r7, HEAP_NUMBER_TYPE); |
| 424 if (strict) { | 433 if (strict) { |
| 425 // If lhs is not a number and rhs is a smi then strict equality cannot | 434 // If lhs is not a number and rhs is a smi then strict equality cannot |
| 426 // succeed. Return non-equal. | 435 // succeed. Return non-equal. |
| 427 // If lhs is r3 then there is already a non zero value in it. | 436 // If lhs is r3 then there is already a non zero value in it. |
| 437 Label skip; |
| 438 __ beq(&skip); |
| 428 if (!lhs.is(r3)) { | 439 if (!lhs.is(r3)) { |
| 429 Label skip; | |
| 430 __ beq(&skip); | |
| 431 __ mov(r3, Operand(NOT_EQUAL)); | 440 __ mov(r3, Operand(NOT_EQUAL)); |
| 432 __ Ret(); | |
| 433 __ bind(&skip); | |
| 434 } else { | |
| 435 __ Ret(ne); | |
| 436 } | 441 } |
| 442 __ Ret(); |
| 443 __ bind(&skip); |
| 437 } else { | 444 } else { |
| 438 // Smi compared non-strictly with a non-smi non-heap-number. Call | 445 // Smi compared non-strictly with a non-smi non-heap-number. Call |
| 439 // the runtime. | 446 // the runtime. |
| 440 __ bne(slow); | 447 __ bne(slow); |
| 441 } | 448 } |
| 442 | 449 |
| 443 // Rhs is a smi, lhs is a heap number. | 450 // Rhs is a smi, lhs is a heap number. |
| 444 // Load the double from lhs, tagged HeapNumber r4, to d7. | 451 // Load the double from lhs, tagged HeapNumber r4, to d7. |
| 445 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); | 452 __ lfd(d7, FieldMemOperand(lhs, HeapNumber::kValueOffset)); |
| 446 // Convert rhs to a double in d6. | 453 // Convert rhs to a double in d6. |
| (...skipping 3513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3960 // Handle not identical strings. | 3967 // Handle not identical strings. |
| 3961 | 3968 |
| 3962 // Check that both strings are internalized strings. If they are, we're done | 3969 // Check that both strings are internalized strings. If they are, we're done |
| 3963 // because we already know they are not identical. We know they are both | 3970 // because we already know they are not identical. We know they are both |
| 3964 // strings. | 3971 // strings. |
| 3965 if (equality) { | 3972 if (equality) { |
| 3966 DCHECK(GetCondition() == eq); | 3973 DCHECK(GetCondition() == eq); |
| 3967 STATIC_ASSERT(kInternalizedTag == 0); | 3974 STATIC_ASSERT(kInternalizedTag == 0); |
| 3968 __ orx(tmp3, tmp1, tmp2); | 3975 __ orx(tmp3, tmp1, tmp2); |
| 3969 __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); | 3976 __ andi(r0, tmp3, Operand(kIsNotInternalizedMask)); |
| 3977 __ bne(&is_symbol, cr0); |
| 3970 // Make sure r3 is non-zero. At this point input operands are | 3978 // Make sure r3 is non-zero. At this point input operands are |
| 3971 // guaranteed to be non-zero. | 3979 // guaranteed to be non-zero. |
| 3972 DCHECK(right.is(r3)); | 3980 DCHECK(right.is(r3)); |
| 3973 __ Ret(eq, cr0); | 3981 __ Ret(); |
| 3982 __ bind(&is_symbol); |
| 3974 } | 3983 } |
| 3975 | 3984 |
| 3976 // Check that both strings are sequential one-byte. | 3985 // Check that both strings are sequential one-byte. |
| 3977 Label runtime; | 3986 Label runtime; |
| 3978 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, | 3987 __ JumpIfBothInstanceTypesAreNotSequentialOneByte(tmp1, tmp2, tmp3, tmp4, |
| 3979 &runtime); | 3988 &runtime); |
| 3980 | 3989 |
| 3981 // Compare flat one-byte strings. Returns when done. | 3990 // Compare flat one-byte strings. Returns when done. |
| 3982 if (equality) { | 3991 if (equality) { |
| 3983 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, | 3992 StringHelper::GenerateFlatOneByteStringEquals(masm, left, right, tmp1, |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4200 // the hash in a separate instruction. The value hash + i + i * i is right | 4209 // the hash in a separate instruction. The value hash + i + i * i is right |
| 4201 // shifted in the following and instruction. | 4210 // shifted in the following and instruction. |
| 4202 DCHECK(NameDictionary::GetProbeOffset(i) < | 4211 DCHECK(NameDictionary::GetProbeOffset(i) < |
| 4203 1 << (32 - Name::kHashFieldOffset)); | 4212 1 << (32 - Name::kHashFieldOffset)); |
| 4204 __ addi(scratch2, scratch2, | 4213 __ addi(scratch2, scratch2, |
| 4205 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); | 4214 Operand(NameDictionary::GetProbeOffset(i) << Name::kHashShift)); |
| 4206 } | 4215 } |
| 4207 __ srwi(scratch2, scratch2, Operand(Name::kHashShift)); | 4216 __ srwi(scratch2, scratch2, Operand(Name::kHashShift)); |
| 4208 __ and_(scratch2, scratch1, scratch2); | 4217 __ and_(scratch2, scratch1, scratch2); |
| 4209 | 4218 |
| 4210 // Scale the index by multiplying by the entry size. | 4219 // Scale the index by multiplying by the element size. |
| 4211 STATIC_ASSERT(NameDictionary::kEntrySize == 3); | 4220 STATIC_ASSERT(NameDictionary::kEntrySize == 3); |
| 4212 // scratch2 = scratch2 * 3. | 4221 // scratch2 = scratch2 * 3. |
| 4213 __ ShiftLeftImm(ip, scratch2, Operand(1)); | 4222 __ ShiftLeftImm(ip, scratch2, Operand(1)); |
| 4214 __ add(scratch2, scratch2, ip); | 4223 __ add(scratch2, scratch2, ip); |
| 4215 | 4224 |
| 4216 // Check if the key is identical to the name. | 4225 // Check if the key is identical to the name. |
| 4217 __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2)); | 4226 __ ShiftLeftImm(ip, scratch2, Operand(kPointerSizeLog2)); |
| 4218 __ add(scratch2, elements, ip); | 4227 __ add(scratch2, elements, ip); |
| 4219 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); | 4228 __ LoadP(ip, FieldMemOperand(scratch2, kElementsStartOffset)); |
| 4220 __ cmp(name, ip); | 4229 __ cmp(name, ip); |
| (...skipping 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5305 Label fast_elements_case; | 5314 Label fast_elements_case; |
| 5306 __ cmpi(r6, Operand(FAST_ELEMENTS)); | 5315 __ cmpi(r6, Operand(FAST_ELEMENTS)); |
| 5307 __ beq(&fast_elements_case); | 5316 __ beq(&fast_elements_case); |
| 5308 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 5317 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
| 5309 | 5318 |
| 5310 __ bind(&fast_elements_case); | 5319 __ bind(&fast_elements_case); |
| 5311 GenerateCase(masm, FAST_ELEMENTS); | 5320 GenerateCase(masm, FAST_ELEMENTS); |
| 5312 } | 5321 } |
| 5313 | 5322 |
| 5314 | 5323 |
| 5315 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
| 5316 Register context = cp; | |
| 5317 Register result = r3; | |
| 5318 Register slot = r5; | |
| 5319 | |
| 5320 // Go up the context chain to the script context. | |
| 5321 for (int i = 0; i < depth(); ++i) { | |
| 5322 __ LoadP(result, ContextOperand(context, Context::PREVIOUS_INDEX)); | |
| 5323 context = result; | |
| 5324 } | |
| 5325 | |
| 5326 // Load the PropertyCell value at the specified slot. | |
| 5327 __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); | |
| 5328 __ add(result, context, r0); | |
| 5329 __ LoadP(result, ContextOperand(result)); | |
| 5330 __ LoadP(result, FieldMemOperand(result, PropertyCell::kValueOffset)); | |
| 5331 | |
| 5332 // If the result is not the_hole, return. Otherwise, handle in the runtime. | |
| 5333 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | |
| 5334 __ Ret(ne); | |
| 5335 | |
| 5336 // Fallback to runtime. | |
| 5337 __ SmiTag(slot); | |
| 5338 __ Push(slot); | |
| 5339 __ TailCallRuntime(Runtime::kLoadGlobalViaContext, 1, 1); | |
| 5340 } | |
| 5341 | |
| 5342 | |
| 5343 void StoreGlobalViaContextStub::Generate(MacroAssembler* masm) { | |
| 5344 Register value = r3; | |
| 5345 Register slot = r5; | |
| 5346 | |
| 5347 Register cell = r4; | |
| 5348 Register cell_details = r6; | |
| 5349 Register cell_value = r7; | |
| 5350 Register cell_value_map = r8; | |
| 5351 Register scratch = r9; | |
| 5352 | |
| 5353 Register context = cp; | |
| 5354 Register context_temp = cell; | |
| 5355 | |
| 5356 Label fast_heapobject_case, fast_smi_case, slow_case; | |
| 5357 | |
| 5358 if (FLAG_debug_code) { | |
| 5359 __ CompareRoot(value, Heap::kTheHoleValueRootIndex); | |
| 5360 __ Check(ne, kUnexpectedValue); | |
| 5361 } | |
| 5362 | |
| 5363 // Go up the context chain to the script context. | |
| 5364 for (int i = 0; i < depth(); i++) { | |
| 5365 __ LoadP(context_temp, ContextOperand(context, Context::PREVIOUS_INDEX)); | |
| 5366 context = context_temp; | |
| 5367 } | |
| 5368 | |
| 5369 // Load the PropertyCell at the specified slot. | |
| 5370 __ ShiftLeftImm(r0, slot, Operand(kPointerSizeLog2)); | |
| 5371 __ add(cell, context, r0); | |
| 5372 __ LoadP(cell, ContextOperand(cell)); | |
| 5373 | |
| 5374 // Load PropertyDetails for the cell (actually only the cell_type and kind). | |
| 5375 __ LoadP(cell_details, FieldMemOperand(cell, PropertyCell::kDetailsOffset)); | |
| 5376 __ SmiUntag(cell_details); | |
| 5377 __ andi(cell_details, cell_details, | |
| 5378 Operand(PropertyDetails::PropertyCellTypeField::kMask | | |
| 5379 PropertyDetails::KindField::kMask | | |
| 5380 PropertyDetails::kAttributesReadOnlyMask)); | |
| 5381 | |
| 5382 // Check if PropertyCell holds mutable data. | |
| 5383 Label not_mutable_data; | |
| 5384 __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( | |
| 5385 PropertyCellType::kMutable) | | |
| 5386 PropertyDetails::KindField::encode(kData))); | |
| 5387 __ bne(¬_mutable_data); | |
| 5388 __ JumpIfSmi(value, &fast_smi_case); | |
| 5389 | |
| 5390 __ bind(&fast_heapobject_case); | |
| 5391 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); | |
| 5392 // RecordWriteField clobbers the value register, so we copy it before the | |
| 5393 // call. | |
| 5394 __ mr(r6, value); | |
| 5395 __ RecordWriteField(cell, PropertyCell::kValueOffset, r6, scratch, | |
| 5396 kLRHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, | |
| 5397 OMIT_SMI_CHECK); | |
| 5398 __ Ret(); | |
| 5399 | |
| 5400 __ bind(¬_mutable_data); | |
| 5401 // Check if PropertyCell value matches the new value (relevant for Constant, | |
| 5402 // ConstantType and Undefined cells). | |
| 5403 Label not_same_value; | |
| 5404 __ LoadP(cell_value, FieldMemOperand(cell, PropertyCell::kValueOffset)); | |
| 5405 __ cmp(cell_value, value); | |
| 5406 __ bne(¬_same_value); | |
| 5407 | |
| 5408 // Make sure the PropertyCell is not marked READ_ONLY. | |
| 5409 __ andi(r0, cell_details, Operand(PropertyDetails::kAttributesReadOnlyMask)); | |
| 5410 __ bne(&slow_case, cr0); | |
| 5411 | |
| 5412 if (FLAG_debug_code) { | |
| 5413 Label done; | |
| 5414 // This can only be true for Constant, ConstantType and Undefined cells, | |
| 5415 // because we never store the_hole via this stub. | |
| 5416 __ cmpi(cell_details, | |
| 5417 Operand(PropertyDetails::PropertyCellTypeField::encode( | |
| 5418 PropertyCellType::kConstant) | | |
| 5419 PropertyDetails::KindField::encode(kData))); | |
| 5420 __ beq(&done); | |
| 5421 __ cmpi(cell_details, | |
| 5422 Operand(PropertyDetails::PropertyCellTypeField::encode( | |
| 5423 PropertyCellType::kConstantType) | | |
| 5424 PropertyDetails::KindField::encode(kData))); | |
| 5425 __ beq(&done); | |
| 5426 __ cmpi(cell_details, | |
| 5427 Operand(PropertyDetails::PropertyCellTypeField::encode( | |
| 5428 PropertyCellType::kUndefined) | | |
| 5429 PropertyDetails::KindField::encode(kData))); | |
| 5430 __ Check(eq, kUnexpectedValue); | |
| 5431 __ bind(&done); | |
| 5432 } | |
| 5433 __ Ret(); | |
| 5434 __ bind(¬_same_value); | |
| 5435 | |
| 5436 // Check if PropertyCell contains data with constant type (and is not | |
| 5437 // READ_ONLY). | |
| 5438 __ cmpi(cell_details, Operand(PropertyDetails::PropertyCellTypeField::encode( | |
| 5439 PropertyCellType::kConstantType) | | |
| 5440 PropertyDetails::KindField::encode(kData))); | |
| 5441 __ bne(&slow_case); | |
| 5442 | |
| 5443 // Now either both old and new values must be smis or both must be heap | |
| 5444 // objects with same map. | |
| 5445 Label value_is_heap_object; | |
| 5446 __ JumpIfNotSmi(value, &value_is_heap_object); | |
| 5447 __ JumpIfNotSmi(cell_value, &slow_case); | |
| 5448 // Old and new values are smis, no need for a write barrier here. | |
| 5449 __ bind(&fast_smi_case); | |
| 5450 __ StoreP(value, FieldMemOperand(cell, PropertyCell::kValueOffset), r0); | |
| 5451 __ Ret(); | |
| 5452 | |
| 5453 __ bind(&value_is_heap_object); | |
| 5454 __ JumpIfSmi(cell_value, &slow_case); | |
| 5455 | |
| 5456 __ LoadP(cell_value_map, FieldMemOperand(cell_value, HeapObject::kMapOffset)); | |
| 5457 __ LoadP(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); | |
| 5458 __ cmp(cell_value_map, scratch); | |
| 5459 __ beq(&fast_heapobject_case); | |
| 5460 | |
| 5461 // Fallback to runtime. | |
| 5462 __ bind(&slow_case); | |
| 5463 __ SmiTag(slot); | |
| 5464 __ Push(slot, value); | |
| 5465 __ TailCallRuntime(is_strict(language_mode()) | |
| 5466 ? Runtime::kStoreGlobalViaContext_Strict | |
| 5467 : Runtime::kStoreGlobalViaContext_Sloppy, | |
| 5468 2, 1); | |
| 5469 } | |
| 5470 | |
| 5471 | |
| 5472 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 5324 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 5473 return ref0.address() - ref1.address(); | 5325 return ref0.address() - ref1.address(); |
| 5474 } | 5326 } |
| 5475 | 5327 |
| 5476 | 5328 |
| 5477 // Calls an API function. Allocates HandleScope, extracts returned value | 5329 // Calls an API function. Allocates HandleScope, extracts returned value |
| 5478 // from handle and propagates exceptions. Restores context. stack_space | 5330 // from handle and propagates exceptions. Restores context. stack_space |
| 5479 // - space to be unwound on exit (includes the call JS arguments space and | 5331 // - space to be unwound on exit (includes the call JS arguments space and |
| 5480 // the additional space allocated for the fast call). | 5332 // the additional space allocated for the fast call). |
| 5481 static void CallApiFunctionAndReturn(MacroAssembler* masm, | 5333 static void CallApiFunctionAndReturn(MacroAssembler* masm, |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5826 kStackUnwindSpace, NULL, | 5678 kStackUnwindSpace, NULL, |
| 5827 MemOperand(fp, 6 * kPointerSize), NULL); | 5679 MemOperand(fp, 6 * kPointerSize), NULL); |
| 5828 } | 5680 } |
| 5829 | 5681 |
| 5830 | 5682 |
| 5831 #undef __ | 5683 #undef __ |
| 5832 } // namespace internal | 5684 } // namespace internal |
| 5833 } // namespace v8 | 5685 } // namespace v8 |
| 5834 | 5686 |
| 5835 #endif // V8_TARGET_ARCH_PPC | 5687 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |