Changeset 137683 in webkit
- Timestamp:
- Dec 13, 2012 4:32:55 PM (11 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r137505 r137683 1 2012-13-11 Oliver Hunt <oliver@apple.com> 2 3 Support op_typeof in the DFG 4 https://bugs.webkit.org/show_bug.cgi?id=98898 5 6 Reviewed by Filip Pizlo. 7 8 Adds a TypeOf node to the DFG to support op_typeof. 9 10 * dfg/DFGAbstractState.cpp: 11 (JSC::DFG::AbstractState::execute): 12 We try to determine the result early here, and substitute in a constant. 13 Otherwise we leave the node intact, and set the result type to SpecString. 14 * dfg/DFGByteCodeParser.cpp: 15 (JSC::DFG::ByteCodeParser::parseBlock): 16 Parse op_typeof 17 * dfg/DFGCSEPhase.cpp: 18 (JSC::DFG::CSEPhase::performNodeCSE): 19 TypeOf nodes can be subjected to pure CSE 20 * dfg/DFGCapabilities.h: 21 (JSC::DFG::canCompileOpcode): 22 We can handle typeof. 23 * dfg/DFGNodeType.h: 24 (DFG): 25 Define the node. 26 * dfg/DFGOperations.cpp: 27 * dfg/DFGOperations.h: 28 Add operationTypeOf to support the non-trivial cases. 29 * dfg/DFGPredictionPropagationPhase.cpp: 30 (JSC::DFG::PredictionPropagationPhase::propagate): 31 * dfg/DFGSpeculativeJIT32_64.cpp: 32 (JSC::DFG::SpeculativeJIT::compile): 33 * dfg/DFGSpeculativeJIT64.cpp: 34 (JSC::DFG::SpeculativeJIT::compile): 35 Actual codegen 36 * runtime/Operations.cpp: 37 (JSC::jsTypeStringForValue): 38 (JSC): 39 * runtime/Operations.h: 40 (JSC): 41 Some refactoring to allow us to get the type string for an 42 object without needing a callframe. 43 1 44 2012-12-12 Filip Pizlo <fpizlo@apple.com> 2 45 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
r137247 r137683 32 32 #include "DFGBasicBlock.h" 33 33 #include "GetByIdStatus.h" 34 #include "Operations.h" 34 35 #include "PutByIdStatus.h" 35 36 … … 708 709 constantWasSet = trySetConstant(nodeIndex, jsBoolean(isJSString(child))); 709 710 break; 711 case IsObject: 712 if (child.isNull() || !child.isObject()) { 713 constantWasSet = trySetConstant(nodeIndex, jsBoolean(child.isNull())); 714 break; 715 } 710 716 default: 711 717 constantWasSet = false; … … 717 723 } 718 724 } 725 719 726 forNode(nodeIndex).set(SpecBoolean); 727 break; 728 } 729 730 case TypeOf: { 731 JSGlobalData* globalData = m_codeBlock->globalData(); 732 JSValue child = forNode(node.child1()).value(); 733 AbstractValue& abstractChild = forNode(node.child1()); 734 if (child) { 735 JSValue typeString = jsTypeStringForValue(*globalData, m_codeBlock->globalObjectFor(node.codeOrigin), child); 736 if (trySetConstant(nodeIndex, typeString)) { 737 m_foundConstants = true; 738 break; 739 } 740 } else if (isNumberSpeculation(abstractChild.m_type)) { 741 if (trySetConstant(nodeIndex, globalData->smallStrings.numberString(globalData))) { 742 forNode(node.child1()).filter(SpecNumber); 743 m_foundConstants = true; 744 break; 745 } 746 } else if (isStringSpeculation(abstractChild.m_type)) { 747 if (trySetConstant(nodeIndex, globalData->smallStrings.stringString(globalData))) { 748 forNode(node.child1()).filter(SpecString); 749 m_foundConstants = true; 750 break; 751 } 752 } else if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) { 753 if (trySetConstant(nodeIndex, globalData->smallStrings.objectString(globalData))) { 754 forNode(node.child1()).filter(SpecFinalObject | SpecArray | SpecArguments); 755 m_foundConstants = true; 756 break; 757 } 758 } else if (isFunctionSpeculation(abstractChild.m_type)) { 759 if (trySetConstant(nodeIndex, globalData->smallStrings.functionString(globalData))) { 760 forNode(node.child1()).filter(SpecFunction); 761 m_foundConstants = true; 762 break; 763 } 764 } else if (isBooleanSpeculation(abstractChild.m_type)) { 765 if (trySetConstant(nodeIndex, globalData->smallStrings.booleanString(globalData))) { 766 forNode(node.child1()).filter(SpecBoolean); 767 m_foundConstants = true; 768 break; 769 } 770 } else { 771 Node& childNode = m_graph[node.child1()]; 772 if (isCellSpeculation(childNode.prediction())) { 773 if (isStringSpeculation(childNode.prediction())) 774 forNode(node.child1()).filter(SpecString); 775 else 776 forNode(node.child1()).filter(SpecCell); 777 node.setCanExit(true); 778 } 779 } 780 forNode(nodeIndex).set(SpecString); 720 781 break; 721 782 } -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r137379 r137683 3256 3256 } 3257 3257 3258 case op_typeof: { 3259 set(currentInstruction[1].u.operand, 3260 addToGraph(TypeOf, get(currentInstruction[2].u.operand))); 3261 NEXT_OPCODE(op_typeof); 3262 } 3263 3258 3264 default: 3259 3265 // Parse failed! This should not happen because the capabilities checker -
trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
r137247 r137683 563 563 case AllocatePropertyStorage: 564 564 case ReallocatePropertyStorage: 565 case TypeOf: 565 566 return NoNode; 566 567 … … 1128 1129 case SkipScope: 1129 1130 case GetScopeRegisters: 1131 case TypeOf: 1130 1132 setReplacement(pureCSE(node)); 1131 1133 break; -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h
r137094 r137683 197 197 case op_put_to_base_variable: 198 198 case op_put_to_base: 199 case op_typeof: 199 200 return CanCompile; 200 201 -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r136601 r137683 211 211 macro(IsObject, NodeResultBoolean) \ 212 212 macro(IsFunction, NodeResultBoolean) \ 213 macro(TypeOf, NodeResultJS) \ 213 214 macro(LogicalNot, NodeResultBoolean) \ 214 215 macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ -
trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp
r137247 r137683 1369 1369 { 1370 1370 return jsIsFunctionType(JSValue::decode(value)); 1371 } 1372 1373 JSCell* DFG_OPERATION operationTypeOf(ExecState* exec, JSCell* value) 1374 { 1375 return jsTypeStringForValue(exec, JSValue(value)).asCell(); 1371 1376 } 1372 1377 -
trunk/Source/JavaScriptCore/dfg/DFGOperations.h
r137247 r137683 199 199 size_t DFG_OPERATION operationIsObject(ExecState*, EncodedJSValue) WTF_INTERNAL; 200 200 size_t DFG_OPERATION operationIsFunction(EncodedJSValue) WTF_INTERNAL; 201 JSCell* DFG_OPERATION operationTypeOf(ExecState*, JSCell*) WTF_INTERNAL; 201 202 void DFG_OPERATION operationReallocateStorageAndFinishPut(ExecState*, JSObject*, Structure*, PropertyOffset, EncodedJSValue) WTF_INTERNAL; 202 203 char* DFG_OPERATION operationAllocatePropertyStorageWithInitialCapacity(ExecState*) WTF_INTERNAL; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r136601 r137683 498 498 break; 499 499 } 500 500 501 case TypeOf: { 502 changed |= setPrediction(SpecString); 503 changed |= mergeDefaultFlags(node); 504 break; 505 } 506 501 507 case GetById: { 502 508 changed |= mergePrediction(node.getHeapPrediction()); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r136601 r137683 4559 4559 break; 4560 4560 } 4561 case TypeOf: { 4562 JSValueOperand value(this, node.child1()); 4563 GPRReg tagGPR = value.tagGPR(); 4564 GPRReg payloadGPR = value.payloadGPR(); 4565 GPRTemporary temp(this); 4566 GPRReg tempGPR = temp.gpr(); 4567 GPRResult result(this); 4568 GPRReg resultGPR = result.gpr(); 4569 JITCompiler::JumpList doneJumps; 4570 4571 flushRegisters(); 4572 4573 JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, tagGPR, JITCompiler::TrustedImm32(JSValue::CellTag)); 4574 Node& child = m_jit.graph()[node.child1()]; 4575 if (child.shouldSpeculateCell()) 4576 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1(), isNotCell); 4577 4578 if (!child.shouldSpeculateNonStringCell()) { 4579 m_jit.loadPtr(JITCompiler::Address(payloadGPR, JSCell::structureOffset()), tempGPR); 4580 JITCompiler::Jump notString = m_jit.branch8(JITCompiler::NotEqual, JITCompiler::Address(tempGPR, Structure::typeInfoTypeOffset()), TrustedImm32(StringType)); 4581 if (child.shouldSpeculateString()) 4582 speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1(), notString); 4583 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.stringString(m_jit.globalData())), resultGPR); 4584 doneJumps.append(m_jit.jump()); 4585 if (!child.shouldSpeculateString()) { 4586 notString.link(&m_jit); 4587 callOperation(operationTypeOf, resultGPR, payloadGPR); 4588 doneJumps.append(m_jit.jump()); 4589 } 4590 } else { 4591 callOperation(operationTypeOf, resultGPR, payloadGPR); 4592 doneJumps.append(m_jit.jump()); 4593 } 4594 4595 if (!child.shouldSpeculateCell()) { 4596 isNotCell.link(&m_jit); 4597 4598 m_jit.add32(TrustedImm32(1), tagGPR, tempGPR); 4599 JITCompiler::Jump notNumber = m_jit.branch32(JITCompiler::AboveOrEqual, tempGPR, JITCompiler::TrustedImm32(JSValue::LowestTag + 1)); 4600 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.numberString(m_jit.globalData())), resultGPR); 4601 doneJumps.append(m_jit.jump()); 4602 notNumber.link(&m_jit); 4603 4604 JITCompiler::Jump notUndefined = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::UndefinedTag)); 4605 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.undefinedString(m_jit.globalData())), resultGPR); 4606 doneJumps.append(m_jit.jump()); 4607 notUndefined.link(&m_jit); 4608 4609 JITCompiler::Jump notNull = m_jit.branch32(JITCompiler::NotEqual, tagGPR, TrustedImm32(JSValue::NullTag)); 4610 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.objectString(m_jit.globalData())), resultGPR); 4611 doneJumps.append(m_jit.jump()); 4612 notNull.link(&m_jit); 4613 4614 // Only boolean left 4615 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.booleanString(m_jit.globalData())), resultGPR); 4616 } 4617 doneJumps.link(&m_jit); 4618 cellResult(resultGPR, m_compileIndex); 4619 break; 4620 } 4561 4621 4562 4622 case Phi: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r136601 r137683 4070 4070 4071 4071 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly); 4072 4072 4073 4073 break; 4074 4074 } … … 4482 4482 m_jit.or32(TrustedImm32(ValueFalse), resultGPR); 4483 4483 jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); 4484 break; 4485 } 4486 4487 case TypeOf: { 4488 JSValueOperand value(this, node.child1()); 4489 GPRReg valueGPR = value.gpr(); 4490 GPRTemporary temp(this); 4491 GPRReg tempGPR = temp.gpr(); 4492 GPRResult result(this); 4493 GPRReg resultGPR = result.gpr(); 4494 JITCompiler::JumpList doneJumps; 4495 4496 flushRegisters(); 4497 4498 JITCompiler::Jump isNotCell = m_jit.branchTest64(JITCompiler::NonZero, valueGPR, GPRInfo::tagMaskRegister); 4499 Node& child = m_jit.graph()[node.child1()]; 4500 if (child.shouldSpeculateCell()) 4501 speculationCheck(BadType, JSValueSource(valueGPR), node.child1(), isNotCell); 4502 4503 if (!child.shouldSpeculateNonStringCell()) { 4504 m_jit.loadPtr(JITCompiler::Address(valueGPR, JSCell::structureOffset()), tempGPR); 4505 JITCompiler::Jump notString = m_jit.branch8(JITCompiler::NotEqual, JITCompiler::Address(tempGPR, Structure::typeInfoTypeOffset()), TrustedImm32(StringType)); 4506 if (child.shouldSpeculateString()) 4507 speculationCheck(BadType, JSValueSource(valueGPR), node.child1(), notString); 4508 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.stringString(m_jit.globalData())), resultGPR); 4509 doneJumps.append(m_jit.jump()); 4510 if (!child.shouldSpeculateString()) { 4511 notString.link(&m_jit); 4512 callOperation(operationTypeOf, resultGPR, valueGPR); 4513 doneJumps.append(m_jit.jump()); 4514 } 4515 } else { 4516 callOperation(operationTypeOf, resultGPR, valueGPR); 4517 doneJumps.append(m_jit.jump()); 4518 } 4519 4520 if (!child.shouldSpeculateCell()) { 4521 isNotCell.link(&m_jit); 4522 JITCompiler::Jump notNumber = m_jit.branchTest64(JITCompiler::Zero, valueGPR, GPRInfo::tagTypeNumberRegister); 4523 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.numberString(m_jit.globalData())), resultGPR); 4524 doneJumps.append(m_jit.jump()); 4525 notNumber.link(&m_jit); 4526 4527 JITCompiler::Jump notUndefined = m_jit.branch64(JITCompiler::NotEqual, valueGPR, JITCompiler::TrustedImm64(ValueUndefined)); 4528 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.undefinedString(m_jit.globalData())), resultGPR); 4529 doneJumps.append(m_jit.jump()); 4530 notUndefined.link(&m_jit); 4531 4532 JITCompiler::Jump notNull = m_jit.branch64(JITCompiler::NotEqual, valueGPR, JITCompiler::TrustedImm64(ValueNull)); 4533 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.objectString(m_jit.globalData())), resultGPR); 4534 doneJumps.append(m_jit.jump()); 4535 notNull.link(&m_jit); 4536 4537 // Only boolean left 4538 m_jit.move(TrustedImmPtr(m_jit.globalData()->smallStrings.booleanString(m_jit.globalData())), resultGPR); 4539 } 4540 doneJumps.link(&m_jit); 4541 cellResult(resultGPR, m_compileIndex); 4484 4542 break; 4485 4543 } -
trunk/Source/JavaScriptCore/runtime/Operations.cpp
r126494 r137683 57 57 } 58 58 59 JSValue jsTypeStringForValue( CallFrame* callFrame, JSValue v)59 JSValue jsTypeStringForValue(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue v) 60 60 { 61 JSGlobalData& globalData = callFrame->globalData();62 61 if (v.isUndefined()) 63 62 return globalData.smallStrings.undefinedString(&globalData); … … 71 70 // Return "undefined" for objects that should be treated 72 71 // as null when doing comparisons. 73 if (asObject(v)->structure()->masqueradesAsUndefined( callFrame->lexicalGlobalObject()))72 if (asObject(v)->structure()->masqueradesAsUndefined(globalObject)) 74 73 return globalData.smallStrings.undefinedString(&globalData); 75 74 CallData callData; … … 79 78 } 80 79 return globalData.smallStrings.objectString(&globalData); 80 } 81 82 JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v) 83 { 84 return jsTypeStringForValue(callFrame->globalData(), callFrame->lexicalGlobalObject(), v); 81 85 } 82 86 -
trunk/Source/JavaScriptCore/runtime/Operations.h
r135454 r137683 33 33 NEVER_INLINE JSValue jsAddSlowCase(CallFrame*, JSValue, JSValue); 34 34 JSValue jsTypeStringForValue(CallFrame*, JSValue); 35 JSValue jsTypeStringForValue(JSGlobalData&, JSGlobalObject*, JSValue); 35 36 bool jsIsObjectType(CallFrame*, JSValue); 36 37 bool jsIsFunctionType(JSValue);
Note: See TracChangeset
for help on using the changeset viewer.