Changeset 189082 in webkit
- Timestamp:
- Aug 27, 2015, 7:28:35 PM (10 years ago)
- Location:
- trunk/Source
- Files:
-
- 33 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r189079 r189082 1 2015-08-27 Commit Queue <commit-queue@webkit.org> 2 3 Unreviewed, rolling out r189079. 4 https://bugs.webkit.org/show_bug.cgi?id=148555 5 6 broke the build (Requested by jessieberlin on #webkit). 7 8 Reverted changeset: 9 10 "Create WebAssembly functions" 11 https://bugs.webkit.org/show_bug.cgi?id=148373 12 http://trac.webkit.org/changeset/189079 13 1 14 2015-08-27 Sukolsak Sakshuwong <sukolsak@gmail.com> 2 15 -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp
r189079 r189082 108 108 if (!m_hash) { 109 109 RELEASE_ASSERT(isSafeToComputeHash()); 110 m_hash = CodeBlockHash(owner ScriptExecutable()->source(), specializationKind());110 m_hash = CodeBlockHash(ownerExecutable()->source(), specializationKind()); 111 111 } 112 112 return m_hash; … … 116 116 { 117 117 if (codeType() != FunctionCode) 118 return owner ScriptExecutable()->source().toUTF8();118 return ownerExecutable()->source().toUTF8(); 119 119 120 120 SourceProvider* provider = source(); … … 156 156 if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined) 157 157 out.print(" (ShouldAlwaysBeInlined)"); 158 if (owner ScriptExecutable()->neverInline())158 if (ownerExecutable()->neverInline()) 159 159 out.print(" (NeverInline)"); 160 if (owner ScriptExecutable()->didTryToEnterInLoop())160 if (ownerExecutable()->didTryToEnterInLoop()) 161 161 out.print(" (DidTryToEnterInLoop)"); 162 if (owner ScriptExecutable()->isStrictMode())162 if (ownerExecutable()->isStrictMode()) 163 163 out.print(" (StrictMode)"); 164 164 if (this->jitType() == JITCode::BaselineJIT && m_didFailFTLCompilation) … … 553 553 void CodeBlock::dumpSource(PrintStream& out) 554 554 { 555 ScriptExecutable* executable = owner ScriptExecutable();555 ScriptExecutable* executable = ownerExecutable(); 556 556 if (executable->isFunctionExecutable()) { 557 557 FunctionExecutable* functionExecutable = reinterpret_cast<FunctionExecutable*>(executable); … … 1752 1752 1753 1753 if (vm()->typeProfiler() || vm()->controlFlowProfiler()) 1754 vm()->functionHasExecutedCache()->removeUnexecutedRange( ownerExecutable->sourceID(), ownerExecutable->typeProfilingStartOffset(),ownerExecutable->typeProfilingEndOffset());1754 vm()->functionHasExecutedCache()->removeUnexecutedRange(m_ownerExecutable->sourceID(), m_ownerExecutable->typeProfilingStartOffset(), m_ownerExecutable->typeProfilingEndOffset()); 1755 1755 1756 1756 setConstantRegisters(unlinkedCodeBlock->constantRegisters(), unlinkedCodeBlock->constantsSourceCodeRepresentation()); … … 1786 1786 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i); 1787 1787 if (vm()->typeProfiler() || vm()->controlFlowProfiler()) 1788 vm()->functionHasExecutedCache()->insertUnexecutedRange( ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());1788 vm()->functionHasExecutedCache()->insertUnexecutedRange(m_ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset()); 1789 1789 m_functionDecls[i].set(*m_vm, ownerExecutable, unlinkedExecutable->link(*m_vm, ownerExecutable->source())); 1790 1790 } … … 1794 1794 UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i); 1795 1795 if (vm()->typeProfiler() || vm()->controlFlowProfiler()) 1796 vm()->functionHasExecutedCache()->insertUnexecutedRange( ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset());1796 vm()->functionHasExecutedCache()->insertUnexecutedRange(m_ownerExecutable->sourceID(), unlinkedExecutable->typeProfilingStartOffset(), unlinkedExecutable->typeProfilingEndOffset()); 1797 1797 m_functionExprs[i].set(*m_vm, ownerExecutable, unlinkedExecutable->link(*m_vm, ownerExecutable->source())); 1798 1798 } … … 1926 1926 instructions[i + opLength - 1] = objectAllocationProfile; 1927 1927 objectAllocationProfile->initialize(*vm(), 1928 ownerExecutable, m_globalObject->objectPrototype(), inferredInlineCapacity);1928 m_ownerExecutable.get(), m_globalObject->objectPrototype(), inferredInlineCapacity); 1929 1929 break; 1930 1930 } … … 2107 2107 // Currently, the text offset that is used as identification is "f" in the function keyword 2108 2108 // and is stored on TypeLocation's m_divotForFunctionOffsetIfReturnStatement member variable. 2109 divotStart = divotEnd = ownerExecutable->typeProfilingStartOffset();2109 divotStart = divotEnd = m_ownerExecutable->typeProfilingStartOffset(); 2110 2110 shouldAnalyze = true; 2111 2111 } … … 2115 2115 2116 2116 std::pair<TypeLocation*, bool> locationPair = vm()->typeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID, 2117 ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, vm());2117 m_ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, vm()); 2118 2118 TypeLocation* location = locationPair.first; 2119 2119 bool isNewLocation = locationPair.second; 2120 2120 2121 2121 if (flag == ProfileTypeBytecodeFunctionReturnStatement) 2122 location->m_divotForFunctionOffsetIfReturnStatement = ownerExecutable->typeProfilingStartOffset();2122 location->m_divotForFunctionOffsetIfReturnStatement = m_ownerExecutable->typeProfilingStartOffset(); 2123 2123 2124 2124 if (shouldAnalyze && isNewLocation) … … 2163 2163 m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock) + m_instructions.size() * sizeof(Instruction)); 2164 2164 } 2165 2166 #if ENABLE(WEBASSEMBLY)2167 CodeBlock::CodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)2168 : m_globalObject(globalObject->vm(), ownerExecutable, globalObject)2169 , m_heap(&m_globalObject->vm().heap)2170 , m_numCalleeRegisters(0)2171 , m_numVars(0)2172 , m_isConstructor(false)2173 , m_shouldAlwaysBeInlined(false)2174 , m_didFailFTLCompilation(false)2175 , m_hasBeenCompiledWithFTL(false)2176 , m_hasDebuggerStatement(false)2177 , m_steppingMode(SteppingModeDisabled)2178 , m_numBreakpoints(0)2179 , m_ownerExecutable(m_globalObject->vm(), ownerExecutable, ownerExecutable)2180 , m_vm(&vm)2181 , m_isStrictMode(false)2182 , m_needsActivation(false)2183 , m_mayBeExecuting(false)2184 , m_codeType(FunctionCode)2185 , m_osrExitCounter(0)2186 , m_optimizationDelayCounter(0)2187 , m_reoptimizationRetryCounter(0)2188 #if ENABLE(JIT)2189 , m_capabilityLevelState(DFG::CannotCompile)2190 #endif2191 {2192 ASSERT(m_heap->isDeferred());2193 2194 m_heap->m_codeBlocks.add(this);2195 m_heap->reportExtraMemoryAllocated(sizeof(CodeBlock));2196 }2197 #endif2198 2165 2199 2166 CodeBlock::~CodeBlock() … … 2542 2509 { 2543 2510 Interpreter* interpreter = m_vm->interpreter; 2544 bool ownedByWebAssemblyExecutable = false; 2545 #if ENABLE(WEBASSEMBLY) 2546 ownedByWebAssemblyExecutable = m_ownerExecutable->isWebAssemblyExecutable(); 2547 #endif 2548 if (JITCode::couldBeInterpreted(jitType()) && !ownedByWebAssemblyExecutable) { 2511 if (JITCode::couldBeInterpreted(jitType())) { 2549 2512 const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions(); 2550 2513 for (size_t size = propertyAccessInstructions.size(), i = 0; i < size; ++i) { … … 2951 2914 { 2952 2915 RELEASE_ASSERT(bytecodeOffset < instructions().size()); 2953 return ownerScriptExecutable()->firstLine() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset);2916 return m_ownerExecutable->firstLine() + m_unlinkedCode->lineNumberForBytecodeOffset(bytecodeOffset); 2954 2917 } 2955 2918 … … 2970 2933 divot += m_sourceOffset; 2971 2934 column += line ? 1 : firstLineColumnOffset(); 2972 line += ownerScriptExecutable()->firstLine();2935 line += m_ownerExecutable->firstLine(); 2973 2936 } 2974 2937 … … 3047 3010 void CodeBlock::install() 3048 3011 { 3049 owner ScriptExecutable()->installCode(this);3012 ownerExecutable()->installCode(this); 3050 3013 } 3051 3014 3052 3015 PassRefPtr<CodeBlock> CodeBlock::newReplacement() 3053 3016 { 3054 return owner ScriptExecutable()->newReplacementCodeBlockFor(specializationKind());3017 return ownerExecutable()->newReplacementCodeBlockFor(specializationKind()); 3055 3018 } 3056 3019 … … 3087 3050 return DFG::functionForCallCapabilityLevel(this); 3088 3051 } 3089 3090 #if ENABLE(WEBASSEMBLY)3091 CodeBlock* WebAssemblyCodeBlock::replacement()3092 {3093 return nullptr;3094 }3095 3096 DFG::CapabilityLevel WebAssemblyCodeBlock::capabilityLevelInternal()3097 {3098 return DFG::CannotCompile;3099 }3100 #endif3101 3052 #endif 3102 3053 … … 3651 3602 void CodeBlock::updateAllPredictions() 3652 3603 { 3653 #if ENABLE(WEBASSEMBLY)3654 if (m_ownerExecutable->isWebAssemblyExecutable())3655 return;3656 #endif3657 3604 updateAllValueProfilePredictions(); 3658 3605 updateAllArrayPredictions(); … … 3972 3919 basicBlockEndOffset = instructions[endIdx + 1].u.operand - 1; 3973 3920 } else { 3974 basicBlockEndOffset = m_sourceOffset + ownerScriptExecutable()->source().length() - 1; // Offset before the closing brace.3921 basicBlockEndOffset = m_sourceOffset + m_ownerExecutable->source().length() - 1; // Offset before the closing brace. 3975 3922 basicBlockStartOffset = std::min(basicBlockStartOffset, basicBlockEndOffset); // Some start offsets may be at the closing brace, ensure it is the offset before. 3976 3923 } … … 4000 3947 } 4001 3948 4002 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation( ownerScriptExecutable()->sourceID(), basicBlockStartOffset, basicBlockEndOffset);3949 BasicBlockLocation* basicBlockLocation = vm()->controlFlowProfiler()->getBasicBlockLocation(m_ownerExecutable->sourceID(), basicBlockStartOffset, basicBlockEndOffset); 4003 3950 4004 3951 // Find all functions that are enclosed within the range: [basicBlockStartOffset, basicBlockEndOffset] -
trunk/Source/JavaScriptCore/bytecode/CodeBlock.h
r189079 r189082 97 97 98 98 CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock*, JSScope*, PassRefPtr<SourceProvider>, unsigned sourceOffset, unsigned firstLineColumnOffset); 99 #if ENABLE(WEBASSEMBLY)100 CodeBlock(WebAssemblyExecutable* ownerExecutable, VM&, JSGlobalObject*);101 #endif102 99 103 100 WriteBarrier<JSGlobalObject> m_globalObject; … … 307 304 void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization, const FireDetail* = nullptr); 308 305 309 ExecutableBase* ownerExecutable() const { return m_ownerExecutable.get(); } 310 ScriptExecutable* ownerScriptExecutable() const { return jsCast<ScriptExecutable*>(m_ownerExecutable.get()); } 306 ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); } 311 307 312 308 void setVM(VM* vm) { m_vm = vm; } … … 351 347 } 352 348 353 CodeType codeType() const 354 { 355 #if ENABLE(WEBASSEMBLY) 356 if (m_ownerExecutable->isWebAssemblyExecutable()) 357 return FunctionCode; 358 #endif 359 return m_unlinkedCode->codeType(); 360 } 361 349 CodeType codeType() const { return m_unlinkedCode->codeType(); } 362 350 PutPropertySlot::Context putByIdContext() const 363 351 { … … 996 984 }; 997 985 }; 998 WriteBarrier< ExecutableBase> m_ownerExecutable;986 WriteBarrier<ScriptExecutable> m_ownerExecutable; 999 987 VM* m_vm; 1000 988 … … 1147 1135 }; 1148 1136 1149 #if ENABLE(WEBASSEMBLY)1150 class WebAssemblyCodeBlock : public CodeBlock {1151 public:1152 WebAssemblyCodeBlock(CopyParsedBlockTag, WebAssemblyCodeBlock& other)1153 : CodeBlock(CopyParsedBlock, other)1154 {1155 }1156 1157 WebAssemblyCodeBlock(WebAssemblyExecutable* ownerExecutable, VM& vm, JSGlobalObject* globalObject)1158 : CodeBlock(ownerExecutable, vm, globalObject)1159 {1160 }1161 1162 #if ENABLE(JIT)1163 protected:1164 virtual CodeBlock* replacement() override;1165 virtual DFG::CapabilityLevel capabilityLevelInternal() override;1166 #endif1167 };1168 #endif1169 1170 1137 inline Register& ExecState::r(int index) 1171 1138 { -
trunk/Source/JavaScriptCore/debugger/Debugger.cpp
r189079 r189082 228 228 void Debugger::toggleBreakpoint(CodeBlock* codeBlock, Breakpoint& breakpoint, BreakpointState enabledOrNot) 229 229 { 230 ScriptExecutable* executable = codeBlock->owner ScriptExecutable();230 ScriptExecutable* executable = codeBlock->ownerExecutable(); 231 231 232 232 SourceID sourceID = static_cast<SourceID>(executable->sourceID()); -
trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp
r189079 r189082 243 243 if (!codeBlock) 244 244 return noSourceID; 245 return codeBlock->owner ScriptExecutable()->sourceID();245 return codeBlock->ownerExecutable()->sourceID(); 246 246 } 247 247 -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r189079 r189082 940 940 InlineCallFrame* m_inlineCallFrame; 941 941 942 ScriptExecutable* executable() { return m_codeBlock->owner ScriptExecutable(); }942 ScriptExecutable* executable() { return m_codeBlock->ownerExecutable(); } 943 943 944 944 QueryableExitProfile m_exitProfile; … … 1253 1253 dataLog(" Might compile function: ", mightCompileFunctionFor(codeBlock, kind), "\n"); 1254 1254 dataLog(" Is supported for inlining: ", isSupportedForInlining(codeBlock), "\n"); 1255 dataLog(" Needs activation: ", codeBlock->owner ScriptExecutable()->needsActivation(), "\n");1256 dataLog(" Is inlining candidate: ", codeBlock->owner ScriptExecutable()->isInliningCandidate(), "\n");1255 dataLog(" Needs activation: ", codeBlock->ownerExecutable()->needsActivation(), "\n"); 1256 dataLog(" Is inlining candidate: ", codeBlock->ownerExecutable()->isInliningCandidate(), "\n"); 1257 1257 } 1258 1258 if (!canInline(capabilityLevel)) { … … 4437 4437 // The owner is the machine code block, and we already have a barrier on that when the 4438 4438 // plan finishes. 4439 m_inlineCallFrame->executable.setWithoutWriteBarrier(codeBlock->owner ScriptExecutable());4439 m_inlineCallFrame->executable.setWithoutWriteBarrier(codeBlock->ownerExecutable()); 4440 4440 m_inlineCallFrame->setStackOffset(inlineCallFrameStart.offset() - JSStack::CallFrameHeaderSize); 4441 4441 if (callee) { … … 4530 4530 dataLog( 4531 4531 ": needsActivation = ", codeBlock->needsActivation(), 4532 ", isStrictMode = ", codeBlock->owner ScriptExecutable()->isStrictMode(), "\n");4532 ", isStrictMode = ", codeBlock->ownerExecutable()->isStrictMode(), "\n"); 4533 4533 codeBlock->baselineVersion()->dumpBytecode(); 4534 4534 } -
trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp
r189079 r189082 45 45 bool isSupportedForInlining(CodeBlock* codeBlock) 46 46 { 47 #if ENABLE(WEBASSEMBLY) 48 if (codeBlock->ownerExecutable()->isWebAssemblyExecutable()) 49 return false; 50 #endif 51 return codeBlock->ownerScriptExecutable()->isInliningCandidate(); 47 return codeBlock->ownerExecutable()->isInliningCandidate(); 52 48 } 53 49 -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r189079 r189082 346 346 { 347 347 if (!inlineCallFrame) 348 return m_codeBlock->owner ScriptExecutable();348 return m_codeBlock->ownerExecutable(); 349 349 350 350 return inlineCallFrame->executable.get(); -
trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp
r189079 r189082 113 113 114 114 if (bytecodeIndex) 115 codeBlock->owner ScriptExecutable()->setDidTryToEnterInLoop(true);115 codeBlock->ownerExecutable()->setDidTryToEnterInLoop(true); 116 116 117 117 if (codeBlock->jitType() != JITCode::DFGJIT) { -
trunk/Source/JavaScriptCore/inspector/ScriptCallStackFactory.cpp
r189079 r189082 67 67 68 68 if (m_remainingCapacityForFrameCapture) { 69 #if ENABLE(WEBASSEMBLY)70 if (visitor->codeBlock()->ownerExecutable()->isWebAssemblyExecutable())71 return StackVisitor::Continue;72 #endif73 69 unsigned line; 74 70 unsigned column; -
trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp
r189079 r189082 169 169 170 170 ThisTDZMode thisTDZMode = callerCodeBlock->unlinkedCodeBlock()->constructorKind() == ConstructorKind::Derived ? ThisTDZMode::AlwaysCheck : ThisTDZMode::CheckIfNeeded; 171 eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->owner ScriptExecutable(), callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain);171 eval = callerCodeBlock->evalCodeCache().getSlow(callFrame, callerCodeBlock->ownerExecutable(), callerCodeBlock->isStrictMode(), thisTDZMode, programSource, callerScopeChain); 172 172 if (!eval) 173 173 return jsUndefined(); … … 516 516 } 517 517 518 static inline bool isWebAssemblyExecutable(ExecutableBase* executable)519 {520 #if !ENABLE(WEBASSEMBLY)521 UNUSED_PARAM(executable);522 return false;523 #else524 return executable->isWebAssemblyExecutable();525 #endif526 }527 528 518 class GetStackTraceFunctor { 529 519 public: … … 539 529 VM& vm = m_vm; 540 530 if (m_remainingCapacityForFrameCapture) { 541 if (visitor->isJSFrame() 542 && !isWebAssemblyExecutable(visitor->codeBlock()->ownerExecutable()) 543 && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) { 531 if (visitor->isJSFrame() && !visitor->codeBlock()->unlinkedCodeBlock()->isBuiltinFunction()) { 544 532 CodeBlock* codeBlock = visitor->codeBlock(); 545 533 StackFrame s = { 546 534 Strong<JSObject>(vm, visitor->callee()), 547 535 getStackFrameCodeType(visitor), 548 Strong<ScriptExecutable>(vm, codeBlock->owner ScriptExecutable()),536 Strong<ScriptExecutable>(vm, codeBlock->ownerExecutable()), 549 537 Strong<UnlinkedCodeBlock>(vm, codeBlock->unlinkedCodeBlock()), 550 538 codeBlock->source(), 551 codeBlock->owner ScriptExecutable()->firstLine(),539 codeBlock->ownerExecutable()->firstLine(), 552 540 codeBlock->firstLineColumnOffset(), 553 541 codeBlock->sourceOffset(), … … 642 630 unsigned bytecodeOffset = visitor->bytecodeOffset(); 643 631 644 if (m_isTermination || !(m_handler = (m_codeBlock && !isWebAssemblyExecutable(m_codeBlock->ownerExecutable()))? m_codeBlock->handlerForBytecodeOffset(bytecodeOffset) : nullptr)) {632 if (m_isTermination || !(m_handler = m_codeBlock ? m_codeBlock->handlerForBytecodeOffset(bytecodeOffset) : nullptr)) { 645 633 if (!unwindCallFrame(visitor)) { 646 634 if (LegacyProfiler* profiler = vm.enabledProfiler()) -
trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp
r189079 r189082 222 222 case CodeType::Function: 223 223 case CodeType::Global: { 224 String sourceURL = codeBlock()->owner ScriptExecutable()->sourceURL();224 String sourceURL = codeBlock()->ownerExecutable()->sourceURL(); 225 225 if (!sourceURL.isEmpty()) 226 226 traceLine = sourceURL.impl(); … … 293 293 retrieveExpressionInfo(divot, unusedStartOffset, unusedEndOffset, divotLine, divotColumn); 294 294 295 line = divotLine + codeBlock->owner ScriptExecutable()->firstLine();295 line = divotLine + codeBlock->ownerExecutable()->firstLine(); 296 296 column = divotColumn + (divotLine ? 1 : codeBlock->firstLineColumnOffset()); 297 297 298 if (codeBlock->owner ScriptExecutable()->hasOverrideLineNumber())299 line = codeBlock->owner ScriptExecutable()->overrideLineNumber();298 if (codeBlock->ownerExecutable()->hasOverrideLineNumber()) 299 line = codeBlock->ownerExecutable()->overrideLineNumber(); 300 300 } 301 301 -
trunk/Source/JavaScriptCore/jit/JITOperations.cpp
r189079 r189082 849 849 MacroAssemblerCodePtr codePtr; 850 850 CodeBlock* codeBlock = 0; 851 if (executable->isHostFunction()) {851 if (executable->isHostFunction()) 852 852 codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()); 853 #if ENABLE(WEBASSEMBLY) 854 } else if (executable->isWebAssemblyExecutable()) { 855 WebAssemblyExecutable* webAssemblyExecutable = static_cast<WebAssemblyExecutable*>(executable); 856 webAssemblyExecutable->prepareForExecution(execCallee); 857 codeBlock = webAssemblyExecutable->codeBlockForCall(); 858 ASSERT(codeBlock); 859 ArityCheckMode arity; 860 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())) 861 arity = MustCheckArity; 862 else 863 arity = ArityCheckNotRequired; 864 codePtr = webAssemblyExecutable->entrypointFor(*vm, kind, arity, callLinkInfo->registerPreservationMode()); 865 #endif 866 } else { 853 else { 867 854 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 868 855 … … 910 897 ExecutableBase* executable = function->executable(); 911 898 if (UNLIKELY(!executable->hasJITCodeFor(kind))) { 912 bool isWebAssemblyExecutable = false; 913 #if ENABLE(WEBASSEMBLY) 914 isWebAssemblyExecutable = executable->isWebAssemblyExecutable(); 915 #endif 916 if (!isWebAssemblyExecutable) { 917 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 918 919 if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) { 920 exec->vm().throwException(exec, createNotAConstructorError(exec, function)); 921 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); 922 } 923 924 JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind); 925 if (error) { 926 exec->vm().throwException(exec, error); 927 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); 928 } 929 } else { 930 #if ENABLE(WEBASSEMBLY) 931 if (!isCall(kind)) { 932 exec->vm().throwException(exec, createNotAConstructorError(exec, function)); 933 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); 934 } 935 936 WebAssemblyExecutable* webAssemblyExecutable = static_cast<WebAssemblyExecutable*>(executable); 937 webAssemblyExecutable->prepareForExecution(execCallee); 938 #endif 899 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 900 901 if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct) { 902 exec->vm().throwException(exec, createNotAConstructorError(exec, function)); 903 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); 904 } 905 906 JSObject* error = functionExecutable->prepareForExecution(execCallee, function, scope, kind); 907 if (error) { 908 exec->vm().throwException(exec, error); 909 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress()); 939 910 } 940 911 } -
trunk/Source/JavaScriptCore/jit/Repatch.cpp
r189079 r189082 1743 1743 codeBlock = nullptr; 1744 1744 else { 1745 ExecutableBase* executable = variant.executable(); 1746 #if ENABLE(WEBASSEMBLY) 1747 if (executable->isWebAssemblyExecutable()) 1748 codeBlock = jsCast<WebAssemblyExecutable*>(executable)->codeBlockForCall(); 1749 else 1750 #endif 1751 codeBlock = jsCast<FunctionExecutable*>(executable)->codeBlockForCall(); 1745 codeBlock = jsCast<FunctionExecutable*>(variant.executable())->codeBlockForCall(); 1746 1752 1747 // If we cannot handle a callee, assume that it's better for this whole thing to be a 1753 1748 // virtual call. -
trunk/Source/JavaScriptCore/llint/LLIntData.cpp
r189079 r189082 133 133 #endif 134 134 ASSERT(StringType == 6); 135 ASSERT(ObjectType == 1 9);136 ASSERT(FinalObjectType == 20);135 ASSERT(ObjectType == 18); 136 ASSERT(FinalObjectType == 19); 137 137 ASSERT(MasqueradesAsUndefined == 1); 138 138 ASSERT(ImplementsHasInstance == 2); -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r189079 r189082 1117 1117 MacroAssemblerCodePtr codePtr; 1118 1118 CodeBlock* codeBlock = 0; 1119 bool isWebAssemblyExecutable = false; 1120 #if ENABLE(WEBASSEMBLY) 1121 isWebAssemblyExecutable = executable->isWebAssemblyExecutable(); 1122 #endif 1123 1124 if (executable->isHostFunction()) { 1119 if (executable->isHostFunction()) 1125 1120 codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired); 1126 } else if (!isWebAssemblyExecutable){1121 else { 1127 1122 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 1128 1123 … … 1141 1136 arity = ArityCheckNotRequired; 1142 1137 codePtr = functionExecutable->entrypointFor(vm, kind, arity, RegisterPreservationNotRequired); 1143 } else {1144 #if ENABLE(WEBASSEMBLY)1145 WebAssemblyExecutable* webAssemblyExecutable = static_cast<WebAssemblyExecutable*>(executable);1146 webAssemblyExecutable->prepareForExecution(execCallee);1147 codeBlock = webAssemblyExecutable->codeBlockForCall();1148 ASSERT(codeBlock);1149 ArityCheckMode arity;1150 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()))1151 arity = MustCheckArity;1152 else1153 arity = ArityCheckNotRequired;1154 codePtr = webAssemblyExecutable->entrypointFor(vm, kind, arity, RegisterPreservationNotRequired);1155 #endif1156 1138 } 1157 1139 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r189079 r189082 162 162 # Type constants. 163 163 const StringType = 6 164 const ObjectType = 1 9165 const FinalObjectType = 20164 const ObjectType = 18 165 const FinalObjectType = 19 166 166 167 167 # Type flags constants. -
trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
r189079 r189082 526 526 { 527 527 BEGIN(); 528 ExecutableBase* ownerExecutable = exec->codeBlock()->ownerExecutable();528 ScriptExecutable* ownerExecutable = exec->codeBlock()->ownerExecutable(); 529 529 Heap::heap(ownerExecutable)->writeBarrier(ownerExecutable); 530 530 END(); -
trunk/Source/JavaScriptCore/runtime/Executable.cpp
r189079 r189082 32 32 #include "JIT.h" 33 33 #include "JSCInlines.h" 34 #include "JSWASMModule.h"35 34 #include "LLIntEntrypoint.h" 36 35 #include "Parser.h" 37 36 #include "ProfilerDatabase.h" 38 37 #include "TypeProfiler.h" 39 #include "WASMFunctionParser.h"40 38 #include <wtf/CommaPrinter.h> 41 39 #include <wtf/Vector.h> … … 565 563 } 566 564 567 #if ENABLE(WEBASSEMBLY)568 const ClassInfo WebAssemblyExecutable::s_info = { "WebAssemblyExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(WebAssemblyExecutable) };569 570 WebAssemblyExecutable::WebAssemblyExecutable(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)571 : ExecutableBase(vm, vm.webAssemblyExecutableStructure.get(), NUM_PARAMETERS_NOT_COMPILED)572 , m_source(source)573 , m_module(vm, this, module)574 , m_functionIndex(functionIndex)575 {576 }577 578 void WebAssemblyExecutable::destroy(JSCell* cell)579 {580 static_cast<WebAssemblyExecutable*>(cell)->WebAssemblyExecutable::~WebAssemblyExecutable();581 }582 583 void WebAssemblyExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)584 {585 WebAssemblyExecutable* thisObject = jsCast<WebAssemblyExecutable*>(cell);586 ASSERT_GC_OBJECT_INHERITS(thisObject, info());587 ExecutableBase::visitChildren(thisObject, visitor);588 if (thisObject->m_codeBlockForCall)589 thisObject->m_codeBlockForCall->visitAggregate(visitor);590 visitor.append(&thisObject->m_module);591 }592 593 void WebAssemblyExecutable::clearCode()594 {595 m_codeBlockForCall = nullptr;596 Base::clearCode();597 }598 599 void WebAssemblyExecutable::prepareForExecution(ExecState* exec)600 {601 if (hasJITCodeForCall())602 return;603 604 VM& vm = exec->vm();605 DeferGC deferGC(vm.heap);606 607 RefPtr<WebAssemblyCodeBlock> codeBlock = adoptRef(new WebAssemblyCodeBlock(608 this, vm, exec->lexicalGlobalObject()));609 610 WASMFunctionParser::compile(vm, codeBlock.get(), m_module.get(), m_source, m_functionIndex);611 612 m_jitCodeForCall = codeBlock->jitCode();613 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();614 m_jitCodeForCallWithArityCheckAndPreserveRegs = MacroAssemblerCodePtr();615 m_numParametersForCall = codeBlock->numParameters();616 617 m_codeBlockForCall = codeBlock;618 619 Heap::heap(this)->writeBarrier(this);620 }621 #endif622 623 565 void ExecutableBase::dump(PrintStream& out) const 624 566 { -
trunk/Source/JavaScriptCore/runtime/Executable.h
r189079 r189082 51 51 class EvalCodeBlock; 52 52 class FunctionCodeBlock; 53 class JSScope;54 class JSWASMModule;55 53 class LLIntOffsetsExtractor; 56 54 class ProgramCodeBlock; 57 class WebAssemblyCodeBlock;55 class JSScope; 58 56 59 57 enum CompilationKind { FirstCompilation, OptimizingCompilation }; … … 95 93 CodeBlockHash hashFor(CodeSpecializationKind) const; 96 94 97 bool isEvalExecutable() const95 bool isEvalExecutable() 98 96 { 99 97 return type() == EvalExecutableType; 100 98 } 101 bool isFunctionExecutable() const99 bool isFunctionExecutable() 102 100 { 103 101 return type() == FunctionExecutableType; 104 102 } 105 bool isProgramExecutable() const103 bool isProgramExecutable() 106 104 { 107 105 return type() == ProgramExecutableType; … … 113 111 return m_numParametersForCall == NUM_PARAMETERS_IS_HOST; 114 112 } 115 116 #if ENABLE(WEBASSEMBLY)117 bool isWebAssemblyExecutable() const118 {119 return type() == WebAssemblyExecutableType;120 }121 #endif122 113 123 114 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(CellType, StructureFlags), info()); } … … 568 559 static void destroy(JSCell*); 569 560 570 UnlinkedFunctionExecutable* unlinkedExecutable() const561 UnlinkedFunctionExecutable* unlinkedExecutable() 571 562 { 572 563 return m_unlinkedExecutable.get(); … … 682 673 }; 683 674 684 #if ENABLE(WEBASSEMBLY)685 class WebAssemblyExecutable final : public ExecutableBase {686 public:687 typedef ExecutableBase Base;688 static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;689 690 static WebAssemblyExecutable* create(VM& vm, const SourceCode& source, JSWASMModule* module, unsigned functionIndex)691 {692 WebAssemblyExecutable* executable = new (NotNull, allocateCell<WebAssemblyExecutable>(vm.heap)) WebAssemblyExecutable(vm, source, module, functionIndex);693 executable->finishCreation(vm);694 return executable;695 }696 697 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto)698 {699 return Structure::create(vm, globalObject, proto, TypeInfo(WebAssemblyExecutableType, StructureFlags), info());700 }701 702 static void destroy(JSCell*);703 704 DECLARE_INFO;705 706 void clearCode();707 708 void prepareForExecution(ExecState*);709 710 WebAssemblyCodeBlock* codeBlockForCall()711 {712 return m_codeBlockForCall.get();713 }714 715 private:716 WebAssemblyExecutable(VM&, const SourceCode&, JSWASMModule*, unsigned functionIndex);717 718 static void visitChildren(JSCell*, SlotVisitor&);719 720 SourceCode m_source;721 WriteBarrier<JSWASMModule> m_module;722 unsigned m_functionIndex;723 724 RefPtr<WebAssemblyCodeBlock> m_codeBlockForCall;725 };726 #endif727 728 675 inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable) 729 676 { … … 735 682 case FunctionExecutableType: 736 683 return jsCast<FunctionExecutable*>(executable)->clearCode(); 737 #if ENABLE(WEBASSEMBLY)738 case WebAssemblyExecutableType:739 return jsCast<WebAssemblyExecutable*>(executable)->clearCode();740 #endif741 684 default: 742 685 return jsCast<NativeExecutable*>(executable)->clearCode(); -
trunk/Source/JavaScriptCore/runtime/JSFunction.cpp
r189079 r189082 67 67 return result; 68 68 } 69 70 #if ENABLE(WEBASSEMBLY)71 JSFunction* JSFunction::create(VM& vm, WebAssemblyExecutable* executable, JSScope* scope)72 {73 JSFunction* function = new (NotNull, allocateCell<JSFunction>(vm.heap)) JSFunction(vm, executable, scope);74 ASSERT(function->structure()->globalObject());75 function->finishCreation(vm);76 return function;77 }78 #endif79 69 80 70 static inline NativeExecutable* getNativeExecutable(VM& vm, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor) -
trunk/Source/JavaScriptCore/runtime/JSFunction.h
r189079 r189082 41 41 class NativeExecutable; 42 42 class SourceCode; 43 class WebAssemblyExecutable;44 43 namespace DFG { 45 44 class SpeculativeJIT; … … 75 74 76 75 static JSFunction* create(VM&, FunctionExecutable*, JSScope*); 77 #if ENABLE(WEBASSEMBLY)78 static JSFunction* create(VM&, WebAssemblyExecutable*, JSScope*);79 #endif80 76 81 77 static JSFunction* createBuiltinFunction(VM&, FunctionExecutable*, JSGlobalObject*); … … 148 144 JSFunction(VM&, FunctionExecutable*, JSScope*, Structure*); 149 145 150 #if ENABLE(WEBASSEMBLY)151 JSFunction(VM&, WebAssemblyExecutable*, JSScope*);152 #endif153 154 146 void finishCreation(VM&, NativeExecutable*, int length, const String& name); 155 147 using Base::finishCreation; -
trunk/Source/JavaScriptCore/runtime/JSFunctionInlines.h
r189079 r189082 53 53 } 54 54 55 #if ENABLE(WEBASSEMBLY)56 inline JSFunction::JSFunction(VM& vm, WebAssemblyExecutable* executable, JSScope* scope)57 : Base(vm, scope, scope->globalObject()->functionStructure())58 , m_executable(vm, this, executable)59 , m_rareData()60 {61 }62 #endif63 64 55 inline FunctionExecutable* JSFunction::jsExecutable() const 65 56 { … … 76 67 inline bool JSFunction::isBuiltinFunction() const 77 68 { 78 #if ENABLE(WEBASSEMBLY)79 if (m_executable->isWebAssemblyExecutable())80 return false;81 #endif82 69 return !isHostFunction() && jsExecutable()->isBuiltinFunction(); 83 70 } -
trunk/Source/JavaScriptCore/runtime/JSType.h
r189079 r189082 43 43 ProgramExecutableType, 44 44 FunctionExecutableType, 45 WebAssemblyExecutableType,46 45 47 46 UnlinkedFunctionExecutableType, -
trunk/Source/JavaScriptCore/runtime/VM.cpp
r189079 r189082 222 222 programExecutableStructure.set(*this, ProgramExecutable::createStructure(*this, 0, jsNull())); 223 223 functionExecutableStructure.set(*this, FunctionExecutable::createStructure(*this, 0, jsNull())); 224 #if ENABLE(WEBASSEMBLY)225 webAssemblyExecutableStructure.set(*this, WebAssemblyExecutable::createStructure(*this, 0, jsNull()));226 #endif227 224 regExpStructure.set(*this, RegExp::createStructure(*this, 0, jsNull())); 228 225 symbolStructure.set(*this, Symbol::createStructure(*this, 0, jsNull())); -
trunk/Source/JavaScriptCore/runtime/VM.h
r189079 r189082 280 280 Strong<Structure> programExecutableStructure; 281 281 Strong<Structure> functionExecutableStructure; 282 #if ENABLE(WEBASSEMBLY)283 Strong<Structure> webAssemblyExecutableStructure;284 #endif285 282 Strong<Structure> regExpStructure; 286 283 Strong<Structure> symbolStructure; -
trunk/Source/JavaScriptCore/wasm/JSWASMModule.h
r189079 r189082 65 65 Vector<WASMFunctionPointerTable>& functionPointerTables() { return m_functionPointerTables; } 66 66 67 Vector<WriteBarrier<JSFunction>>& functions() { return m_functions; }68 69 67 private: 70 68 JSWASMModule(VM& vm, Structure* structure) -
trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.cpp
r189079 r189082 29 29 #if ENABLE(WEBASSEMBLY) 30 30 31 #include "CCallHelpers.h"32 31 #include "JSWASMModule.h" 33 #include "LinkBuffer.h"34 32 #include "WASMFunctionSyntaxChecker.h" 35 33 … … 60 58 endOffsetInSource = parser.m_reader.offset(); 61 59 return true; 62 }63 64 void WASMFunctionParser::compile(VM& vm, CodeBlock* codeBlock, JSWASMModule* module, const SourceCode&, size_t functionIndex)65 {66 // FIXME: Actually compile the code.67 CCallHelpers jit(&vm, codeBlock);68 MacroAssembler::Label beginLabel = jit.label();69 jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsNumber(0))), GPRInfo::returnValueGPR);70 jit.ret();71 MacroAssembler::Label arityCheck = jit.label();72 jit.jump(beginLabel);73 74 LinkBuffer patchBuffer(vm, jit, codeBlock, JITCompilationMustSucceed);75 MacroAssemblerCodePtr withArityCheck = patchBuffer.locationOf(arityCheck);76 MacroAssembler::CodeRef result = FINALIZE_CODE(patchBuffer, ("Baseline JIT code for WebAssembly"));77 codeBlock->setJITCode(adoptRef(new DirectJITCode(result, withArityCheck, JITCode::BaselineJIT)));78 codeBlock->capabilityLevel();79 80 uint32_t signatureIndex = module->functionDeclarations()[functionIndex].signatureIndex;81 const WASMSignature& signature = module->signatures()[signatureIndex];82 codeBlock->setNumParameters(1 + signature.arguments.size());83 60 } 84 61 -
trunk/Source/JavaScriptCore/wasm/WASMFunctionParser.h
r189079 r189082 37 37 namespace JSC { 38 38 39 class CodeBlock;40 39 class JSWASMModule; 41 class VM;42 40 43 41 class WASMFunctionParser { 44 42 public: 45 43 static bool checkSyntax(JSWASMModule*, const SourceCode&, size_t functionIndex, unsigned startOffsetInSource, unsigned& endOffsetInSource, String& errorMessage); 46 static void compile(VM&, CodeBlock*, JSWASMModule*, const SourceCode&, size_t functionIndex);47 44 48 45 private: -
trunk/Source/JavaScriptCore/wasm/WASMModuleParser.cpp
r189079 r189082 50 50 namespace JSC { 51 51 52 WASMModuleParser::WASMModuleParser(VM& vm, JSGlobalObject* globalObject, const SourceCode& source) 53 : m_vm(vm) 54 , m_globalObject(vm, globalObject) 55 , m_source(source) 52 WASMModuleParser::WASMModuleParser(const SourceCode& source) 53 : m_source(source) 56 54 , m_reader(static_cast<WebAssemblySourceProvider*>(source.provider())->data()) 57 55 { 58 56 } 59 57 60 JSWASMModule* WASMModuleParser::parse( String& errorMessage)61 { 62 m_module.set( m_vm, JSWASMModule::create(m_vm, m_globalObject->wasmModuleStructure()));58 JSWASMModule* WASMModuleParser::parse(VM& vm, JSGlobalObject* globalObject, String& errorMessage) 59 { 60 m_module.set(vm, JSWASMModule::create(vm, globalObject->wasmModuleStructure())); 63 61 parseModule(); 64 62 if (!m_errorMessage.isNull()) { … … 220 218 READ_COMPACT_UINT32_OR_FAIL(numberOfFunctionDeclarations, "Cannot read the number of function declarations."); 221 219 m_module->functionDeclarations().reserveInitialCapacity(numberOfFunctionDeclarations); 222 m_module->functions().reserveInitialCapacity(numberOfFunctionDeclarations);223 220 for (uint32_t i = 0; i < numberOfFunctionDeclarations; ++i) { 224 221 WASMFunctionDeclaration functionDeclaration; … … 269 266 } 270 267 m_reader.setOffset(endOffsetInSource); 271 272 WebAssemblyExecutable* webAssemblyExecutable = WebAssemblyExecutable::create(m_vm, m_source, m_module.get(), functionIndex);273 JSFunction* function = JSFunction::create(m_vm, webAssemblyExecutable, m_globalObject.get());274 m_module->functions().uncheckedAppend(WriteBarrier<JSFunction>(m_vm, m_module.get(), function));275 268 } 276 269 … … 293 286 String exportName; 294 287 READ_STRING_OR_FAIL(exportName, "Cannot read the function export name."); 288 // FIXME: Check that exportName is legal. 295 289 uint32_t functionIndex; 296 290 READ_COMPACT_UINT32_OR_FAIL(functionIndex, "Cannot read the function index."); 297 291 FAIL_IF_FALSE(functionIndex < m_module->functionDeclarations().size(), "The function index is incorrect."); 298 Identifier identifier = Identifier::fromString(&m_vm, exportName); 299 m_module->putDirect(m_vm, identifier, m_module->functions()[functionIndex].get()); 292 // FIXME: Export the function. 300 293 } 301 294 break; … … 308 301 JSWASMModule* parseWebAssembly(ExecState* exec, const SourceCode& source, String& errorMessage) 309 302 { 310 WASMModuleParser moduleParser(exec->vm(), exec->lexicalGlobalObject(),source);311 return moduleParser.parse(errorMessage);303 WASMModuleParser WASMModuleParser(source); 304 return WASMModuleParser.parse(exec->vm(), exec->lexicalGlobalObject(), errorMessage); 312 305 } 313 306 -
trunk/Source/JavaScriptCore/wasm/WASMModuleParser.h
r189079 r189082 43 43 class WASMModuleParser { 44 44 public: 45 WASMModuleParser( VM&, JSGlobalObject*,const SourceCode&);46 JSWASMModule* parse( String& errorMessage);45 WASMModuleParser(const SourceCode&); 46 JSWASMModule* parse(VM&, JSGlobalObject*, String& errorMessage); 47 47 48 48 private: … … 58 58 void parseExportSection(); 59 59 60 VM& m_vm;61 Strong<JSGlobalObject> m_globalObject;62 60 const SourceCode& m_source; 63 61 WASMReader m_reader; -
trunk/Source/WebCore/ChangeLog
r189079 r189082 1 2015-08-27 Commit Queue <commit-queue@webkit.org> 2 3 Unreviewed, rolling out r189079. 4 https://bugs.webkit.org/show_bug.cgi?id=148555 5 6 broke the build (Requested by jessieberlin on #webkit). 7 8 Reverted changeset: 9 10 "Create WebAssembly functions" 11 https://bugs.webkit.org/show_bug.cgi?id=148373 12 http://trac.webkit.org/changeset/189079 13 1 14 2015-08-27 Sukolsak Sakshuwong <sukolsak@gmail.com> 2 15 -
trunk/Source/WebCore/testing/Internals.cpp
r189079 r189082 1464 1464 exec->iterate(iter); 1465 1465 CodeBlock* codeBlock = iter.codeBlock(); 1466 executable = codeBlock->owner ScriptExecutable();1466 executable = codeBlock->ownerExecutable(); 1467 1467 } else if (code.isFunction()) { 1468 1468 JSFunction* funcObj = JSC::jsCast<JSFunction*>(code.toObject(exec));
Note:
See TracChangeset
for help on using the changeset viewer.