Changeset 35037 in webkit for trunk/JavaScriptCore
- Timestamp:
- Jul 7, 2008, 9:01:06 AM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r35027 r35037 1 2008-07-07 Sam Weinig <[email protected]> 2 3 Reviewed by Cameron Zwarich. 4 5 Third step in broad cleanup effort. 6 7 [ File list elided ] 8 1 9 2008-07-06 Sam Weinig <[email protected]> 2 10 -
trunk/JavaScriptCore/VM/CodeGenerator.cpp
r34903 r35037 209 209 210 210 // Shift register indexes in generated code to elide registers allocated by intermediate stack frames. 211 m_globalVarStorageOffset = 211 m_globalVarStorageOffset = -1 - RegisterFile::CallFrameHeaderSize - registerFile->size(); 212 212 213 213 // Add previously defined symbols to bookkeeping. … … 386 386 } 387 387 388 389 388 RegisterID* CodeGenerator::highestUsedRegister() 390 389 { … … 449 448 int src1Index; 450 449 int src2Index; 451 450 452 451 retrieveLastBinaryOp(dstIndex, src1Index, src2Index); 453 452 454 453 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { 455 454 rewindBinaryOp(); … … 461 460 } 462 461 } 463 462 464 463 emitOpcode(target->isForwardLabel() ? op_jtrue : op_loop_if_true); 465 464 instructions().append(cond->index()); … … 471 470 { 472 471 ASSERT(target->isForwardLabel()); 473 472 474 473 if (m_lastOpcodeID == op_less) { 475 474 int dstIndex; 476 475 int src1Index; 477 476 int src2Index; 478 477 479 478 retrieveLastBinaryOp(dstIndex, src1Index, src2Index); 480 479 481 480 if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { 482 481 rewindBinaryOp(); … … 488 487 } 489 488 } 490 489 491 490 emitOpcode(op_jfalse); 492 491 instructions().append(cond->index()); -
trunk/JavaScriptCore/VM/CodeGenerator.h
r34891 r35037 328 328 bool addVar(const Identifier&, bool isConstant, RegisterID*&); 329 329 330 331 330 // Returns the RegisterID corresponding to ident. 332 331 RegisterID* addGlobalVar(const Identifier& ident, bool isConstant) -
trunk/JavaScriptCore/VM/SegmentedVector.h
r34617 r35037 94 94 ASSERT(size == m_size); 95 95 } 96 96 97 private: 97 98 void shrink(size_t size) … … 162 163 Vector<Segment*, 32> m_segments; 163 164 }; 164 } 165 166 } // namespace KJS 165 167 166 168 #endif // SegmentedVector_h -
trunk/JavaScriptCore/kjs/DebuggerCallFrame.h
r34906 r35037 43 43 class DebuggerCallFrame { 44 44 public: 45 typedef enum{45 enum Type { 46 46 ProgramType, 47 47 FunctionType 48 } Type;48 }; 49 49 50 50 DebuggerCallFrame(JSGlobalObject* dynamicGlobalObject, const CodeBlock* codeBlock, ScopeChainNode* scopeChain, Register* r, JSValue* exception) -
trunk/JavaScriptCore/kjs/Parser.cpp
r34791 r35037 1 // -*- c-basic-offset: 4 -*-2 1 /* 3 * This file is part of the KDE libraries4 2 * Copyright (C) 1999-2001 Harri Porten ([email protected]) 5 3 * Copyright (C) 2001 Peter Kelly ([email protected]) 6 * Copyright (C) 2003, 2006, 2007 Apple Inc.4 * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. 7 5 * 8 6 * This library is free software; you can redistribute it and/or … … 25 23 #include "config.h" 26 24 #include "Parser.h" 25 27 26 #include "debugger.h" 28 29 27 #include "lexer.h" 30 28 #include <wtf/HashSet.h> … … 40 38 } 41 39 42 void Parser::parse(ExecState* exec, const UString& sourceURL, int startingLineNumber, 43 PassRefPtr<SourceProvider> prpSource, 40 void Parser::parse(ExecState* exec, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> prpSource, 44 41 int* sourceId, int* errLine, UString* errMsg) 45 42 { 46 43 ASSERT(!m_sourceElements); 47 44 48 45 int defaultSourceId; 49 46 int defaultErrLine; 50 47 UString defaultErrMsg; 51 48 52 49 RefPtr<SourceProvider> source = prpSource; 53 50 … … 61 58 *errLine = -1; 62 59 *errMsg = 0; 63 60 64 61 Lexer& lexer = *exec->lexer(); 65 62 … … 81 78 m_sourceElements.clear(); 82 79 } 83 80 84 81 if (Debugger* debugger = exec->dynamicGlobalObject()->debugger()) 85 82 debugger->sourceParsed(exec, *sourceId, sourceURL, *source, startingLineNumber, *errLine, *errMsg); -
trunk/JavaScriptCore/kjs/Parser.h
r34791 r35037 1 // -*- c-basic-offset: 4 -*-2 1 /* 3 * This file is part of the KDE libraries4 2 * Copyright (C) 1999-2001 Harri Porten ([email protected]) 5 3 * Copyright (C) 2001 Peter Kelly ([email protected]) 6 * Copyright (C) 2003, 2006, 2007 Apple Inc.4 * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved. 7 5 * 8 6 * This library is free software; you can redistribute it and/or … … 26 24 #define Parser_h 27 25 26 #include "SourceProvider.h" 28 27 #include "nodes.h" 29 #include "SourceProvider.h"30 28 #include <wtf/Forward.h> 31 29 #include <wtf/Noncopyable.h> … … 39 37 class UString; 40 38 41 template <typename T> struct ParserRefCountedData : ParserRefCounted { 39 template <typename T> 40 struct ParserRefCountedData : ParserRefCounted { 42 41 ParserRefCountedData(JSGlobalData* globalData) 43 42 : ParserRefCounted(globalData) … … 51 50 public: 52 51 template <class ParsedNode> 53 PassRefPtr<ParsedNode> parse(ExecState*, const UString& sourceURL, int startingLineNumber, 54 PassRefPtr<SourceProvider> source, 52 PassRefPtr<ParsedNode> parse(ExecState*, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source, 55 53 int* sourceId = 0, int* errLine = 0, UString* errMsg = 0); 56 54 … … 79 77 80 78 template <class ParsedNode> 81 PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, const UString& sourceURL, int startingLineNumber, 82 PassRefPtr<SourceProvider> source, 79 PassRefPtr<ParsedNode> Parser::parse(ExecState* exec, const UString& sourceURL, int startingLineNumber, PassRefPtr<SourceProvider> source, 83 80 int* sourceId, int* errLine, UString* errMsg) 84 81 { -
trunk/JavaScriptCore/kjs/debugger.cpp
r33979 r35037 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 2 * Copyright (C) 2008 Apple Inc. All rights reserved. -
trunk/JavaScriptCore/kjs/debugger.h
r34587 r35037 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 * This file is part of the KDE libraries4 2 * Copyright (C) 1999-2001 Harri Porten ([email protected]) 5 3 * Copyright (C) 2001 Peter Kelly ([email protected]) 4 * Copyright (C) 2008 Apple Inc. All rights reserved. 6 5 * 7 6 * This library is free software; you can redistribute it and/or … … 24 23 #define Debugger_h 25 24 25 #include "protect.h" 26 26 #include <wtf/HashSet.h> 27 #include "protect.h"28 27 29 28 namespace KJS { 30 29 31 class DebuggerCallFrame; 32 class ExecState; 33 class JSGlobalObject; 34 class JSObject; 35 class JSValue; 36 class ArgList; 37 class SourceProvider; 38 class UString; 39 40 /** 41 * @internal 42 * 43 * Provides an interface which receives notification about various 44 * script-execution related events such as statement execution and function 45 * calls. 46 */ 47 class Debugger { 48 public: 30 class ArgList; 31 class DebuggerCallFrame; 32 class ExecState; 33 class JSGlobalObject; 34 class JSObject; 35 class JSValue; 36 class SourceProvider; 37 class UString; 49 38 50 /**51 * Creates a new debugger52 */53 Debugger();39 class Debugger { 40 public: 41 Debugger(); 42 virtual ~Debugger(); 54 43 55 /** 56 * Destroys the debugger. If the debugger is attached to any global objects, 57 * it is automatically detached. 58 */ 59 virtual ~Debugger(); 44 void attach(JSGlobalObject*); 45 void detach(JSGlobalObject*); 60 46 61 /** 62 * Attaches the debugger to specified global object. This will cause this 63 * object to receive notification of events during execution. 64 * 65 * If the global object is deleted, it will detach the debugger. 66 * 67 * Note: only one debugger can be attached to a global object at a time. 68 * Attaching another debugger to the same global object will cause the 69 * original debugger to be detached. 70 * 71 * @param The global object to attach to. 72 */ 73 void attach(JSGlobalObject*); 47 virtual void sourceParsed(ExecState*, int sourceId, const UString& sourceURL, 48 const SourceProvider& source, int startingLineNumber, int errorLine, const UString& errorMsg) = 0; 49 virtual void exception(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 50 virtual void atStatement(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 51 virtual void callEvent(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 52 virtual void returnEvent(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 74 53 75 /** 76 * Detach the debugger from a global object. 77 * 78 * @param The global object to detach from. 79 */ 80 void detach(JSGlobalObject*); 54 virtual void willExecuteProgram(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 55 virtual void didExecuteProgram(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 56 virtual void didReachBreakpoint(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 81 57 82 /** 83 * Called to notify the debugger that some javascript source code has 84 * been parsed. For calls to Interpreter::evaluate(), this will be called 85 * with the supplied source code before any other code is parsed. 86 * Other situations in which this may be called include creation of a 87 * function using the Function() constructor, or the eval() function. 88 * 89 * The default implementation does nothing. Override this method if 90 * you want to process this event. 91 * 92 * @param exec The current execution state 93 * @param sourceId The ID of the source code (corresponds to the 94 * sourceId supplied in other functions such as atStatement() 95 * @param sourceURL Where the source code that was parsed came from 96 * @param source The source code that was parsed 97 * @param startingLineNumber The line number at which parsing started 98 * @param errorLine The line number at which parsing encountered an 99 * error, or -1 if the source code was valid and parsed successfully 100 * @param errorMsg The error description, or null if the source code 101 was valid and parsed successfully 102 */ 103 virtual void sourceParsed(ExecState*, int sourceId, const UString& sourceURL, 104 const SourceProvider& source, int startingLineNumber, int errorLine, const UString& errorMsg) = 0; 105 106 /** 107 * Called when an exception is thrown during script execution. 108 * 109 * The default implementation does nothing. Override this method if 110 * you want to process this event. 111 * 112 * @param exec The current execution state 113 * @param sourceId The ID of the source code being executed 114 * @param lineno The line at which the error occurred 115 * @param exceptionObj The exception object 116 */ 117 virtual void exception(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 118 119 /** 120 * Called when a line of the script is reached (before it is executed) 121 * 122 * The default implementation does nothing. Override this method if 123 * you want to process this event. 124 * 125 * @param exec The current execution state 126 * @param sourceId The ID of the source code being executed 127 * @param firstLine The starting line of the statement that is about to be 128 * executed 129 * @param lastLine The ending line of the statement that is about to be 130 * executed (usually the same as firstLine) 131 */ 132 virtual void atStatement(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 133 /** 134 * Called on each function call. Use together with @ref #returnEvent 135 * if you want to keep track of the call stack. 136 * 137 * Note: This only gets called for functions that are declared in ECMAScript 138 * source code or passed to eval(), not for internal KJS or 139 * application-supplied functions. 140 * 141 * The default implementation does nothing. Override this method if 142 * you want to process this event. 143 * 144 * @param exec The current execution state 145 * @param sourceId The ID of the source code being executed 146 * @param lineno The line that is about to be executed 147 */ 148 virtual void callEvent(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 149 150 /** 151 * Called on each function exit. The function being returned from is that 152 * which was supplied in the last callEvent(). 153 * 154 * Note: This only gets called for functions that are declared in ECMAScript 155 * source code or passed to eval(), not for internal KJS or 156 * application-supplied functions. 157 * 158 * The default implementation does nothing. Override this method if 159 * you want to process this event. 160 * 161 * @param exec The current execution state 162 * @param sourceId The ID of the source code being executed 163 * @param lineno The line that is about to be executed 164 */ 165 virtual void returnEvent(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 166 167 virtual void willExecuteProgram(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 168 virtual void didExecuteProgram(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 169 virtual void didReachBreakpoint(const DebuggerCallFrame&, int sourceId, int lineno) = 0; 170 171 private: 172 HashSet<JSGlobalObject*> m_globalObjects; 173 }; 58 private: 59 HashSet<JSGlobalObject*> m_globalObjects; 60 }; 174 61 175 62 } // namespace KJS 176 63 177 #endif 64 #endif // Debugger_h -
trunk/JavaScriptCore/kjs/lexer.cpp
r35016 r35037 63 63 Lexer::Lexer(JSGlobalData* globalData) 64 64 : yylineno(1) 65 , restrKeyword(false)66 , eatNextIdentifier(false)67 , stackToken(-1)68 , lastToken(-1)69 , pos(0)70 , code(0)71 , length(0)72 , atLineStart(true)73 , current(0)74 , next1(0)75 , next2(0)76 , next3(0)65 , m_restrKeyword(false) 66 , m_eatNextIdentifier(false) 67 , m_stackToken(-1) 68 , m_lastToken(-1) 69 , m_position(0) 70 , m_code(0) 71 , m_length(0) 72 , m_atLineStart(true) 73 , m_current(0) 74 , m_next1(0) 75 , m_next2(0) 76 , m_next3(0) 77 77 , m_globalData(globalData) 78 , m ainTable(KJS::mainTable)78 , m_mainTable(KJS::mainTable) 79 79 { 80 80 m_buffer8.reserveCapacity(initialReadBufferCapacity); … … 86 86 Lexer::~Lexer() 87 87 { 88 delete []mainTable.table;88 delete [] m_mainTable.table; 89 89 } 90 90 … … 92 92 { 93 93 yylineno = startingLineNumber; 94 restrKeyword = false;95 delimited = false;96 eatNextIdentifier = false;97 stackToken = -1;98 lastToken = -1;99 100 pos= 0;94 m_restrKeyword = false; 95 m_delimited = false; 96 m_eatNextIdentifier = false; 97 m_stackToken = -1; 98 m_lastToken = -1; 99 100 m_position = 0; 101 101 m_source = source; 102 code = m_source->data();103 length = m_source->length();104 skipLF = false;105 skipCR = false;106 error = false;107 atLineStart = true;102 m_code = m_source->data(); 103 m_length = m_source->length(); 104 m_skipLF = false; 105 m_skipCR = false; 106 m_error = false; 107 m_atLineStart = true; 108 108 109 109 // read first characters … … 117 117 118 118 while (p--) { 119 current =next1;120 next1 =next2;121 next2 =next3;119 m_current = m_next1; 120 m_next1 = m_next2; 121 m_next2 = m_next3; 122 122 do { 123 if ( pos >=length) {124 pos++;125 next3 = -1;123 if (m_position >= m_length) { 124 m_position++; 125 m_next3 = -1; 126 126 break; 127 127 } 128 next3 = code[pos++];129 } while ( next3 == 0xFEFF);128 m_next3 = m_code[m_position++]; 129 } while (m_next3 == 0xFEFF); 130 130 } 131 131 } … … 134 134 void Lexer::nextLine() 135 135 { 136 yylineno++;137 atLineStart = true;136 yylineno++; 137 m_atLineStart = true; 138 138 } 139 139 140 140 void Lexer::setDone(State s) 141 141 { 142 state = s;143 done = true;142 m_state = s; 143 m_done = true; 144 144 } 145 145 146 146 int Lexer::lex(void* p1, void* p2) 147 147 { 148 YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1); 149 YYLTYPE* llocp = static_cast<YYLTYPE*>(p2); 150 int token = 0; 151 state = Start; 152 unsigned short stringType = 0; // either single or double quotes 153 m_buffer8.clear(); 154 m_buffer16.clear(); 155 done = false; 156 terminator = false; 157 skipLF = false; 158 skipCR = false; 159 160 // did we push a token on the stack previously ? 161 // (after an automatic semicolon insertion) 162 if (stackToken >= 0) { 163 setDone(Other); 164 token = stackToken; 165 stackToken = 0; 166 } 167 168 while (!done) { 169 if (skipLF && current != '\n') // found \r but not \n afterwards 170 skipLF = false; 171 if (skipCR && current != '\r') // found \n but not \r afterwards 172 skipCR = false; 173 if (skipLF || skipCR) // found \r\n or \n\r -> eat the second one 174 { 175 skipLF = false; 176 skipCR = false; 177 shift(1); 178 } 179 switch (state) { 180 case Start: 181 if (isWhiteSpace()) { 182 // do nothing 183 } else if (current == '/' && next1 == '/') { 184 shift(1); 185 state = InSingleLineComment; 186 } else if (current == '/' && next1 == '*') { 187 shift(1); 188 state = InMultiLineComment; 189 } else if (current == -1) { 190 if (!terminator && !delimited) { 191 // automatic semicolon insertion if program incomplete 192 token = ';'; 193 stackToken = 0; 194 setDone(Other); 195 } else 196 setDone(Eof); 197 } else if (isLineTerminator()) { 198 nextLine(); 199 terminator = true; 200 if (restrKeyword) { 201 token = ';'; 202 setDone(Other); 148 YYSTYPE* lvalp = static_cast<YYSTYPE*>(p1); 149 YYLTYPE* llocp = static_cast<YYLTYPE*>(p2); 150 int token = 0; 151 m_state = Start; 152 unsigned short stringType = 0; // either single or double quotes 153 m_buffer8.clear(); 154 m_buffer16.clear(); 155 m_done = false; 156 m_terminator = false; 157 m_skipLF = false; 158 m_skipCR = false; 159 160 // did we push a token on the stack previously ? 161 // (after an automatic semicolon insertion) 162 if (m_stackToken >= 0) { 163 setDone(Other); 164 token = m_stackToken; 165 m_stackToken = 0; 166 } 167 168 while (!m_done) { 169 if (m_skipLF && m_current != '\n') // found \r but not \n afterwards 170 m_skipLF = false; 171 if (m_skipCR && m_current != '\r') // found \n but not \r afterwards 172 m_skipCR = false; 173 if (m_skipLF || m_skipCR) { // found \r\n or \n\r -> eat the second one 174 m_skipLF = false; 175 m_skipCR = false; 176 shift(1); 203 177 } 204 } else if (current == '"' || current == '\'') { 205 state = InString; 206 stringType = static_cast<unsigned short>(current); 207 } else if (isIdentStart(current)) { 208 record16(current); 209 state = InIdentifierOrKeyword; 210 } else if (current == '\\') { 211 state = InIdentifierStartUnicodeEscapeStart; 212 } else if (current == '0') { 213 record8(current); 214 state = InNum0; 215 } else if (isDecimalDigit(current)) { 216 record8(current); 217 state = InNum; 218 } else if (current == '.' && isDecimalDigit(next1)) { 219 record8(current); 220 state = InDecimal; 221 // <!-- marks the beginning of a line comment (for www usage) 222 } else if (current == '<' && next1 == '!' && 223 next2 == '-' && next3 == '-') { 178 switch (m_state) { 179 case Start: 180 if (isWhiteSpace()) { 181 // do nothing 182 } else if (m_current == '/' && m_next1 == '/') { 183 shift(1); 184 m_state = InSingleLineComment; 185 } else if (m_current == '/' && m_next1 == '*') { 186 shift(1); 187 m_state = InMultiLineComment; 188 } else if (m_current == -1) { 189 if (!m_terminator && !m_delimited) { 190 // automatic semicolon insertion if program incomplete 191 token = ';'; 192 m_stackToken = 0; 193 setDone(Other); 194 } else 195 setDone(Eof); 196 } else if (isLineTerminator()) { 197 nextLine(); 198 m_terminator = true; 199 if (m_restrKeyword) { 200 token = ';'; 201 setDone(Other); 202 } 203 } else if (m_current == '"' || m_current == '\'') { 204 m_state = InString; 205 stringType = static_cast<unsigned short>(m_current); 206 } else if (isIdentStart(m_current)) { 207 record16(m_current); 208 m_state = InIdentifierOrKeyword; 209 } else if (m_current == '\\') 210 m_state = InIdentifierStartUnicodeEscapeStart; 211 else if (m_current == '0') { 212 record8(m_current); 213 m_state = InNum0; 214 } else if (isDecimalDigit(m_current)) { 215 record8(m_current); 216 m_state = InNum; 217 } else if (m_current == '.' && isDecimalDigit(m_next1)) { 218 record8(m_current); 219 m_state = InDecimal; 220 // <!-- marks the beginning of a line comment (for www usage) 221 } else if (m_current == '<' && m_next1 == '!' && m_next2 == '-' && m_next3 == '-') { 222 shift(3); 223 m_state = InSingleLineComment; 224 // same for --> 225 } else if (m_atLineStart && m_current == '-' && m_next1 == '-' && m_next2 == '>') { 226 shift(2); 227 m_state = InSingleLineComment; 228 } else { 229 token = matchPunctuator(lvalp->intValue, m_current, m_next1, m_next2, m_next3); 230 if (token != -1) 231 setDone(Other); 232 else 233 setDone(Bad); 234 } 235 break; 236 case InString: 237 if (m_current == stringType) { 238 shift(1); 239 setDone(String); 240 } else if (isLineTerminator() || m_current == -1) 241 setDone(Bad); 242 else if (m_current == '\\') 243 m_state = InEscapeSequence; 244 else 245 record16(m_current); 246 break; 247 // Escape Sequences inside of strings 248 case InEscapeSequence: 249 if (isOctalDigit(m_current)) { 250 if (m_current >= '0' && m_current <= '3' && 251 isOctalDigit(m_next1) && isOctalDigit(m_next2)) { 252 record16(convertOctal(m_current, m_next1, m_next2)); 253 shift(2); 254 m_state = InString; 255 } else if (isOctalDigit(m_current) && isOctalDigit(m_next1)) { 256 record16(convertOctal('0', m_current, m_next1)); 257 shift(1); 258 m_state = InString; 259 } else if (isOctalDigit(m_current)) { 260 record16(convertOctal('0', '0', m_current)); 261 m_state = InString; 262 } else 263 setDone(Bad); 264 } else if (m_current == 'x') 265 m_state = InHexEscape; 266 else if (m_current == 'u') 267 m_state = InUnicodeEscape; 268 else if (isLineTerminator()) { 269 nextLine(); 270 m_state = InString; 271 } else { 272 record16(singleEscape(static_cast<unsigned short>(m_current))); 273 m_state = InString; 274 } 275 break; 276 case InHexEscape: 277 if (isHexDigit(m_current) && isHexDigit(m_next1)) { 278 m_state = InString; 279 record16(convertHex(m_current, m_next1)); 280 shift(1); 281 } else if (m_current == stringType) { 282 record16('x'); 283 shift(1); 284 setDone(String); 285 } else { 286 record16('x'); 287 record16(m_current); 288 m_state = InString; 289 } 290 break; 291 case InUnicodeEscape: 292 if (isHexDigit(m_current) && isHexDigit(m_next1) && isHexDigit(m_next2) && isHexDigit(m_next3)) { 293 record16(convertUnicode(m_current, m_next1, m_next2, m_next3)); 294 shift(3); 295 m_state = InString; 296 } else if (m_current == stringType) { 297 record16('u'); 298 shift(1); 299 setDone(String); 300 } else 301 setDone(Bad); 302 break; 303 case InSingleLineComment: 304 if (isLineTerminator()) { 305 nextLine(); 306 m_terminator = true; 307 if (m_restrKeyword) { 308 token = ';'; 309 setDone(Other); 310 } else 311 m_state = Start; 312 } else if (m_current == -1) 313 setDone(Eof); 314 break; 315 case InMultiLineComment: 316 if (m_current == -1) 317 setDone(Bad); 318 else if (isLineTerminator()) 319 nextLine(); 320 else if (m_current == '*' && m_next1 == '/') { 321 m_state = Start; 322 shift(1); 323 } 324 break; 325 case InIdentifierOrKeyword: 326 case InIdentifier: 327 if (isIdentPart(m_current)) 328 record16(m_current); 329 else if (m_current == '\\') 330 m_state = InIdentifierPartUnicodeEscapeStart; 331 else 332 setDone(m_state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier); 333 break; 334 case InNum0: 335 if (m_current == 'x' || m_current == 'X') { 336 record8(m_current); 337 m_state = InHex; 338 } else if (m_current == '.') { 339 record8(m_current); 340 m_state = InDecimal; 341 } else if (m_current == 'e' || m_current == 'E') { 342 record8(m_current); 343 m_state = InExponentIndicator; 344 } else if (isOctalDigit(m_current)) { 345 record8(m_current); 346 m_state = InOctal; 347 } else if (isDecimalDigit(m_current)) { 348 record8(m_current); 349 m_state = InDecimal; 350 } else 351 setDone(Number); 352 break; 353 case InHex: 354 if (isHexDigit(m_current)) 355 record8(m_current); 356 else 357 setDone(Hex); 358 break; 359 case InOctal: 360 if (isOctalDigit(m_current)) 361 record8(m_current); 362 else if (isDecimalDigit(m_current)) { 363 record8(m_current); 364 m_state = InDecimal; 365 } else 366 setDone(Octal); 367 break; 368 case InNum: 369 if (isDecimalDigit(m_current)) 370 record8(m_current); 371 else if (m_current == '.') { 372 record8(m_current); 373 m_state = InDecimal; 374 } else if (m_current == 'e' || m_current == 'E') { 375 record8(m_current); 376 m_state = InExponentIndicator; 377 } else 378 setDone(Number); 379 break; 380 case InDecimal: 381 if (isDecimalDigit(m_current)) 382 record8(m_current); 383 else if (m_current == 'e' || m_current == 'E') { 384 record8(m_current); 385 m_state = InExponentIndicator; 386 } else 387 setDone(Number); 388 break; 389 case InExponentIndicator: 390 if (m_current == '+' || m_current == '-') 391 record8(m_current); 392 else if (isDecimalDigit(m_current)) { 393 record8(m_current); 394 m_state = InExponent; 395 } else 396 setDone(Bad); 397 break; 398 case InExponent: 399 if (isDecimalDigit(m_current)) 400 record8(m_current); 401 else 402 setDone(Number); 403 break; 404 case InIdentifierStartUnicodeEscapeStart: 405 if (m_current == 'u') 406 m_state = InIdentifierStartUnicodeEscape; 407 else 408 setDone(Bad); 409 break; 410 case InIdentifierPartUnicodeEscapeStart: 411 if (m_current == 'u') 412 m_state = InIdentifierPartUnicodeEscape; 413 else 414 setDone(Bad); 415 break; 416 case InIdentifierStartUnicodeEscape: 417 if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) { 418 setDone(Bad); 419 break; 420 } 421 token = convertUnicode(m_current, m_next1, m_next2, m_next3); 422 shift(3); 423 if (!isIdentStart(token)) { 424 setDone(Bad); 425 break; 426 } 427 record16(token); 428 m_state = InIdentifier; 429 break; 430 case InIdentifierPartUnicodeEscape: 431 if (!isHexDigit(m_current) || !isHexDigit(m_next1) || !isHexDigit(m_next2) || !isHexDigit(m_next3)) { 432 setDone(Bad); 433 break; 434 } 435 token = convertUnicode(m_current, m_next1, m_next2, m_next3); 436 shift(3); 437 if (!isIdentPart(token)) { 438 setDone(Bad); 439 break; 440 } 441 record16(token); 442 m_state = InIdentifier; 443 break; 444 default: 445 ASSERT(!"Unhandled state in switch statement"); 446 } 447 448 // move on to the next character 449 if (!m_done) 450 shift(1); 451 if (m_state != Start && m_state != InSingleLineComment) 452 m_atLineStart = false; 453 } 454 455 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad 456 if ((m_state == Number || m_state == Octal || m_state == Hex) && isIdentStart(m_current)) 457 m_state = Bad; 458 459 // terminate string 460 m_buffer8.append('\0'); 461 462 #ifdef KJS_DEBUG_LEX 463 fprintf(stderr, "line: %d ", lineNo()); 464 fprintf(stderr, "yytext (%x): ", m_buffer8[0]); 465 fprintf(stderr, "%s ", m_buffer8.data()); 466 #endif 467 468 double dval = 0; 469 if (m_state == Number) 470 dval = strtod(m_buffer8.data(), 0L); 471 else if (m_state == Hex) { // scan hex numbers 472 const char* p = m_buffer8.data() + 2; 473 while (char c = *p++) { 474 dval *= 16; 475 dval += convertHex(c); 476 } 477 478 if (dval >= mantissaOverflowLowerBound) 479 dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16); 480 481 m_state = Number; 482 } else if (m_state == Octal) { // scan octal number 483 const char* p = m_buffer8.data() + 1; 484 while (char c = *p++) { 485 dval *= 8; 486 dval += c - '0'; 487 } 488 489 if (dval >= mantissaOverflowLowerBound) 490 dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8); 491 492 m_state = Number; 493 } 494 495 #ifdef KJS_DEBUG_LEX 496 switch (m_state) { 497 case Eof: 498 printf("(EOF)\n"); 499 break; 500 case Other: 501 printf("(Other)\n"); 502 break; 503 case Identifier: 504 printf("(Identifier)/(Keyword)\n"); 505 break; 506 case String: 507 printf("(String)\n"); 508 break; 509 case Number: 510 printf("(Number)\n"); 511 break; 512 default: 513 printf("(unknown)"); 514 } 515 #endif 516 517 if (m_state != Identifier) 518 m_eatNextIdentifier = false; 519 520 m_restrKeyword = false; 521 m_delimited = false; 522 llocp->first_line = yylineno; 523 llocp->last_line = yylineno; 524 525 switch (m_state) { 526 case Eof: 527 token = 0; 528 break; 529 case Other: 530 if (token == '}' || token == ';') 531 m_delimited = true; 532 break; 533 case Identifier: 534 // Apply anonymous-function hack below (eat the identifier). 535 if (m_eatNextIdentifier) { 536 m_eatNextIdentifier = false; 537 token = lex(lvalp, llocp); 538 break; 539 } 540 lvalp->ident = makeIdentifier(m_buffer16); 541 token = IDENT; 542 break; 543 case IdentifierOrKeyword: { 544 lvalp->ident = makeIdentifier(m_buffer16); 545 const HashEntry* entry = m_mainTable.entry(m_globalData, *lvalp->ident); 546 if (!entry) { 547 // Lookup for keyword failed, means this is an identifier. 548 token = IDENT; 549 break; 550 } 551 token = entry->integerValue; 552 // Hack for "f = function somename() { ... }"; too hard to get into the grammar. 553 m_eatNextIdentifier = token == FUNCTION && m_lastToken == '='; 554 if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW) 555 m_restrKeyword = true; 556 break; 557 } 558 case String: 559 lvalp->string = makeUString(m_buffer16); 560 token = STRING; 561 break; 562 case Number: 563 lvalp->doubleValue = dval; 564 token = NUMBER; 565 break; 566 case Bad: 567 #ifdef KJS_DEBUG_LEX 568 fprintf(stderr, "yylex: ERROR.\n"); 569 #endif 570 m_error = true; 571 return -1; 572 default: 573 ASSERT(!"unhandled numeration value in switch"); 574 m_error = true; 575 return -1; 576 } 577 m_lastToken = token; 578 return token; 579 } 580 581 bool Lexer::isWhiteSpace() const 582 { 583 return m_current == '\t' || m_current == 0x0b || m_current == 0x0c || isSeparatorSpace(m_current); 584 } 585 586 bool Lexer::isLineTerminator() 587 { 588 bool cr = (m_current == '\r'); 589 bool lf = (m_current == '\n'); 590 if (cr) 591 m_skipLF = true; 592 else if (lf) 593 m_skipCR = true; 594 return cr || lf || m_current == 0x2028 || m_current == 0x2029; 595 } 596 597 bool Lexer::isIdentStart(int c) 598 { 599 return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other)) 600 || c == '$' || c == '_'; 601 } 602 603 bool Lexer::isIdentPart(int c) 604 { 605 return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other 606 | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)) 607 || c == '$' || c == '_'; 608 } 609 610 static bool isDecimalDigit(int c) 611 { 612 return (c >= '0' && c <= '9'); 613 } 614 615 bool Lexer::isHexDigit(int c) 616 { 617 return (c >= '0' && c <= '9' 618 || c >= 'a' && c <= 'f' 619 || c >= 'A' && c <= 'F'); 620 } 621 622 bool Lexer::isOctalDigit(int c) 623 { 624 return (c >= '0' && c <= '7'); 625 } 626 627 int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4) 628 { 629 if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { 630 shift(4); 631 return URSHIFTEQUAL; 632 } 633 if (c1 == '=' && c2 == '=' && c3 == '=') { 224 634 shift(3); 225 state = InSingleLineComment; 226 // same for --> 227 } else if (atLineStart && current == '-' && next1 == '-' && next2 == '>') { 228 shift(2); 229 state = InSingleLineComment; 230 } else { 231 token = matchPunctuator(lvalp->intValue, current, next1, next2, next3); 232 if (token != -1) { 233 setDone(Other); 234 } else { 235 // cerr << "encountered unknown character" << endl; 236 setDone(Bad); 237 } 238 } 239 break; 240 case InString: 241 if (current == stringType) { 242 shift(1); 243 setDone(String); 244 } else if (isLineTerminator() || current == -1) { 245 setDone(Bad); 246 } else if (current == '\\') { 247 state = InEscapeSequence; 248 } else { 249 record16(current); 250 } 251 break; 252 // Escape Sequences inside of strings 253 case InEscapeSequence: 254 if (isOctalDigit(current)) { 255 if (current >= '0' && current <= '3' && 256 isOctalDigit(next1) && isOctalDigit(next2)) { 257 record16(convertOctal(current, next1, next2)); 258 shift(2); 259 state = InString; 260 } else if (isOctalDigit(current) && isOctalDigit(next1)) { 261 record16(convertOctal('0', current, next1)); 262 shift(1); 263 state = InString; 264 } else if (isOctalDigit(current)) { 265 record16(convertOctal('0', '0', current)); 266 state = InString; 267 } else { 268 setDone(Bad); 269 } 270 } else if (current == 'x') 271 state = InHexEscape; 272 else if (current == 'u') 273 state = InUnicodeEscape; 274 else if (isLineTerminator()) { 275 nextLine(); 276 state = InString; 277 } else { 278 record16(singleEscape(static_cast<unsigned short>(current))); 279 state = InString; 280 } 281 break; 282 case InHexEscape: 283 if (isHexDigit(current) && isHexDigit(next1)) { 284 state = InString; 285 record16(convertHex(current, next1)); 286 shift(1); 287 } else if (current == stringType) { 288 record16('x'); 289 shift(1); 290 setDone(String); 291 } else { 292 record16('x'); 293 record16(current); 294 state = InString; 295 } 296 break; 297 case InUnicodeEscape: 298 if (isHexDigit(current) && isHexDigit(next1) && isHexDigit(next2) && isHexDigit(next3)) { 299 record16(convertUnicode(current, next1, next2, next3)); 635 return STREQ; 636 } 637 if (c1 == '!' && c2 == '=' && c3 == '=') { 300 638 shift(3); 301 state = InString; 302 } else if (current == stringType) { 303 record16('u'); 304 shift(1); 305 setDone(String); 306 } else { 307 setDone(Bad); 308 } 309 break; 310 case InSingleLineComment: 311 if (isLineTerminator()) { 312 nextLine(); 313 terminator = true; 314 if (restrKeyword) { 315 token = ';'; 316 setDone(Other); 317 } else 318 state = Start; 319 } else if (current == -1) { 320 setDone(Eof); 321 } 322 break; 323 case InMultiLineComment: 324 if (current == -1) { 325 setDone(Bad); 326 } else if (isLineTerminator()) { 327 nextLine(); 328 } else if (current == '*' && next1 == '/') { 329 state = Start; 330 shift(1); 331 } 332 break; 333 case InIdentifierOrKeyword: 334 case InIdentifier: 335 if (isIdentPart(current)) 336 record16(current); 337 else if (current == '\\') 338 state = InIdentifierPartUnicodeEscapeStart; 339 else 340 setDone(state == InIdentifierOrKeyword ? IdentifierOrKeyword : Identifier); 341 break; 342 case InNum0: 343 if (current == 'x' || current == 'X') { 344 record8(current); 345 state = InHex; 346 } else if (current == '.') { 347 record8(current); 348 state = InDecimal; 349 } else if (current == 'e' || current == 'E') { 350 record8(current); 351 state = InExponentIndicator; 352 } else if (isOctalDigit(current)) { 353 record8(current); 354 state = InOctal; 355 } else if (isDecimalDigit(current)) { 356 record8(current); 357 state = InDecimal; 358 } else { 359 setDone(Number); 360 } 361 break; 362 case InHex: 363 if (isHexDigit(current)) { 364 record8(current); 365 } else { 366 setDone(Hex); 367 } 368 break; 369 case InOctal: 370 if (isOctalDigit(current)) { 371 record8(current); 372 } 373 else if (isDecimalDigit(current)) { 374 record8(current); 375 state = InDecimal; 376 } else 377 setDone(Octal); 378 break; 379 case InNum: 380 if (isDecimalDigit(current)) { 381 record8(current); 382 } else if (current == '.') { 383 record8(current); 384 state = InDecimal; 385 } else if (current == 'e' || current == 'E') { 386 record8(current); 387 state = InExponentIndicator; 388 } else 389 setDone(Number); 390 break; 391 case InDecimal: 392 if (isDecimalDigit(current)) { 393 record8(current); 394 } else if (current == 'e' || current == 'E') { 395 record8(current); 396 state = InExponentIndicator; 397 } else 398 setDone(Number); 399 break; 400 case InExponentIndicator: 401 if (current == '+' || current == '-') { 402 record8(current); 403 } else if (isDecimalDigit(current)) { 404 record8(current); 405 state = InExponent; 406 } else 407 setDone(Bad); 408 break; 409 case InExponent: 410 if (isDecimalDigit(current)) { 411 record8(current); 412 } else 413 setDone(Number); 414 break; 415 case InIdentifierStartUnicodeEscapeStart: 416 if (current == 'u') 417 state = InIdentifierStartUnicodeEscape; 418 else 419 setDone(Bad); 420 break; 421 case InIdentifierPartUnicodeEscapeStart: 422 if (current == 'u') 423 state = InIdentifierPartUnicodeEscape; 424 else 425 setDone(Bad); 426 break; 427 case InIdentifierStartUnicodeEscape: 428 if (!isHexDigit(current) || !isHexDigit(next1) || !isHexDigit(next2) || !isHexDigit(next3)) { 429 setDone(Bad); 430 break; 431 } 432 token = convertUnicode(current, next1, next2, next3); 433 shift(3); 434 if (!isIdentStart(token)) { 435 setDone(Bad); 436 break; 437 } 438 record16(token); 439 state = InIdentifier; 440 break; 441 case InIdentifierPartUnicodeEscape: 442 if (!isHexDigit(current) || !isHexDigit(next1) || !isHexDigit(next2) || !isHexDigit(next3)) { 443 setDone(Bad); 444 break; 445 } 446 token = convertUnicode(current, next1, next2, next3); 447 shift(3); 448 if (!isIdentPart(token)) { 449 setDone(Bad); 450 break; 451 } 452 record16(token); 453 state = InIdentifier; 454 break; 455 default: 456 ASSERT(!"Unhandled state in switch statement"); 457 } 458 459 // move on to the next character 460 if (!done) 461 shift(1); 462 if (state != Start && state != InSingleLineComment) 463 atLineStart = false; 464 } 465 466 // no identifiers allowed directly after numeric literal, e.g. "3in" is bad 467 if ((state == Number || state == Octal || state == Hex) && isIdentStart(current)) 468 state = Bad; 469 470 // terminate string 471 m_buffer8.append('\0'); 472 473 #ifdef KJS_DEBUG_LEX 474 fprintf(stderr, "line: %d ", lineNo()); 475 fprintf(stderr, "yytext (%x): ", m_buffer8[0]); 476 fprintf(stderr, "%s ", buffer8.data()); 477 #endif 478 479 double dval = 0; 480 if (state == Number) { 481 dval = strtod(m_buffer8.data(), 0L); 482 } else if (state == Hex) { // scan hex numbers 483 const char* p = m_buffer8.data() + 2; 484 while (char c = *p++) { 485 dval *= 16; 486 dval += convertHex(c); 487 } 488 489 if (dval >= mantissaOverflowLowerBound) 490 dval = parseIntOverflow(m_buffer8.data() + 2, p - (m_buffer8.data() + 3), 16); 491 492 state = Number; 493 } else if (state == Octal) { // scan octal number 494 const char* p = m_buffer8.data() + 1; 495 while (char c = *p++) { 496 dval *= 8; 497 dval += c - '0'; 498 } 499 500 if (dval >= mantissaOverflowLowerBound) 501 dval = parseIntOverflow(m_buffer8.data() + 1, p - (m_buffer8.data() + 2), 8); 502 503 state = Number; 504 } 505 506 #ifdef KJS_DEBUG_LEX 507 switch (state) { 508 case Eof: 509 printf("(EOF)\n"); 510 break; 511 case Other: 512 printf("(Other)\n"); 513 break; 514 case Identifier: 515 printf("(Identifier)/(Keyword)\n"); 516 break; 517 case String: 518 printf("(String)\n"); 519 break; 520 case Number: 521 printf("(Number)\n"); 522 break; 523 default: 524 printf("(unknown)"); 525 } 526 #endif 527 528 if (state != Identifier) 529 eatNextIdentifier = false; 530 531 restrKeyword = false; 532 delimited = false; 533 llocp->first_line = yylineno; // ??? 534 llocp->last_line = yylineno; 535 536 switch (state) { 537 case Eof: 538 token = 0; 539 break; 540 case Other: 541 if (token == '}' || token == ';') 542 delimited = true; 543 break; 544 case Identifier: 545 // Apply anonymous-function hack below (eat the identifier). 546 if (eatNextIdentifier) { 547 eatNextIdentifier = false; 548 token = lex(lvalp, llocp); 549 break; 550 } 551 lvalp->ident = makeIdentifier(m_buffer16); 552 token = IDENT; 553 break; 554 case IdentifierOrKeyword: { 555 lvalp->ident = makeIdentifier(m_buffer16); 556 const HashEntry* entry = mainTable.entry(m_globalData, *lvalp->ident); 557 if (!entry) { 558 // Lookup for keyword failed, means this is an identifier. 559 token = IDENT; 560 break; 561 } 562 token = entry->integerValue; 563 // Hack for "f = function somename() { ... }"; too hard to get into the grammar. 564 eatNextIdentifier = token == FUNCTION && lastToken == '='; 565 if (token == CONTINUE || token == BREAK || token == RETURN || token == THROW) 566 restrKeyword = true; 567 break; 568 } 569 case String: 570 lvalp->string = makeUString(m_buffer16); 571 token = STRING; 572 break; 573 case Number: 574 lvalp->doubleValue = dval; 575 token = NUMBER; 576 break; 577 case Bad: 578 #ifdef KJS_DEBUG_LEX 579 fprintf(stderr, "yylex: ERROR.\n"); 580 #endif 581 error = true; 582 return -1; 583 default: 584 ASSERT(!"unhandled numeration value in switch"); 585 error = true; 586 return -1; 587 } 588 lastToken = token; 589 return token; 590 } 591 592 bool Lexer::isWhiteSpace() const 593 { 594 return current == '\t' || current == 0x0b || current == 0x0c || isSeparatorSpace(current); 595 } 596 597 bool Lexer::isLineTerminator() 598 { 599 bool cr = (current == '\r'); 600 bool lf = (current == '\n'); 601 if (cr) 602 skipLF = true; 603 else if (lf) 604 skipCR = true; 605 return cr || lf || current == 0x2028 || current == 0x2029; 606 } 607 608 bool Lexer::isIdentStart(int c) 609 { 610 return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other)) 611 || c == '$' || c == '_'; 612 } 613 614 bool Lexer::isIdentPart(int c) 615 { 616 return (category(c) & (Letter_Uppercase | Letter_Lowercase | Letter_Titlecase | Letter_Modifier | Letter_Other 617 | Mark_NonSpacing | Mark_SpacingCombining | Number_DecimalDigit | Punctuation_Connector)) 618 || c == '$' || c == '_'; 619 } 620 621 static bool isDecimalDigit(int c) 622 { 623 return (c >= '0' && c <= '9'); 624 } 625 626 bool Lexer::isHexDigit(int c) 627 { 628 return (c >= '0' && c <= '9' || 629 c >= 'a' && c <= 'f' || 630 c >= 'A' && c <= 'F'); 631 } 632 633 bool Lexer::isOctalDigit(int c) 634 { 635 return (c >= '0' && c <= '7'); 636 } 637 638 int Lexer::matchPunctuator(int& charPos, int c1, int c2, int c3, int c4) 639 { 640 if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { 641 shift(4); 642 return URSHIFTEQUAL; 643 } else if (c1 == '=' && c2 == '=' && c3 == '=') { 644 shift(3); 645 return STREQ; 646 } else if (c1 == '!' && c2 == '=' && c3 == '=') { 647 shift(3); 648 return STRNEQ; 649 } else if (c1 == '>' && c2 == '>' && c3 == '>') { 650 shift(3); 651 return URSHIFT; 652 } else if (c1 == '<' && c2 == '<' && c3 == '=') { 653 shift(3); 654 return LSHIFTEQUAL; 655 } else if (c1 == '>' && c2 == '>' && c3 == '=') { 656 shift(3); 657 return RSHIFTEQUAL; 658 } else if (c1 == '<' && c2 == '=') { 659 shift(2); 660 return LE; 661 } else if (c1 == '>' && c2 == '=') { 662 shift(2); 663 return GE; 664 } else if (c1 == '!' && c2 == '=') { 665 shift(2); 666 return NE; 667 } else if (c1 == '+' && c2 == '+') { 668 shift(2); 669 if (terminator) 670 return AUTOPLUSPLUS; 671 else 672 return PLUSPLUS; 673 } else if (c1 == '-' && c2 == '-') { 674 shift(2); 675 if (terminator) 676 return AUTOMINUSMINUS; 677 else 678 return MINUSMINUS; 679 } else if (c1 == '=' && c2 == '=') { 680 shift(2); 681 return EQEQ; 682 } else if (c1 == '+' && c2 == '=') { 683 shift(2); 684 return PLUSEQUAL; 685 } else if (c1 == '-' && c2 == '=') { 686 shift(2); 687 return MINUSEQUAL; 688 } else if (c1 == '*' && c2 == '=') { 689 shift(2); 690 return MULTEQUAL; 691 } else if (c1 == '/' && c2 == '=') { 692 shift(2); 693 return DIVEQUAL; 694 } else if (c1 == '&' && c2 == '=') { 695 shift(2); 696 return ANDEQUAL; 697 } else if (c1 == '^' && c2 == '=') { 698 shift(2); 699 return XOREQUAL; 700 } else if (c1 == '%' && c2 == '=') { 701 shift(2); 702 return MODEQUAL; 703 } else if (c1 == '|' && c2 == '=') { 704 shift(2); 705 return OREQUAL; 706 } else if (c1 == '<' && c2 == '<') { 707 shift(2); 708 return LSHIFT; 709 } else if (c1 == '>' && c2 == '>') { 710 shift(2); 711 return RSHIFT; 712 } else if (c1 == '&' && c2 == '&') { 713 shift(2); 714 return AND; 715 } else if (c1 == '|' && c2 == '|') { 716 shift(2); 717 return OR; 718 } 719 720 switch(c1) { 721 case '=': 722 case '>': 723 case '<': 724 case ',': 725 case '!': 726 case '~': 727 case '?': 728 case ':': 729 case '.': 730 case '+': 731 case '-': 732 case '*': 733 case '/': 734 case '&': 735 case '|': 736 case '^': 737 case '%': 738 case '(': 739 case ')': 740 case '[': 741 case ']': 742 case ';': 743 shift(1); 744 return static_cast<int>(c1); 745 case '{': 746 charPos = pos - 4; 747 shift(1); 748 return OPENBRACE; 749 case '}': 750 charPos = pos - 4; 751 shift(1); 752 return CLOSEBRACE; 753 default: 754 return -1; 755 } 639 return STRNEQ; 640 } 641 if (c1 == '>' && c2 == '>' && c3 == '>') { 642 shift(3); 643 return URSHIFT; 644 } 645 if (c1 == '<' && c2 == '<' && c3 == '=') { 646 shift(3); 647 return LSHIFTEQUAL; 648 } 649 if (c1 == '>' && c2 == '>' && c3 == '=') { 650 shift(3); 651 return RSHIFTEQUAL; 652 } 653 if (c1 == '<' && c2 == '=') { 654 shift(2); 655 return LE; 656 } 657 if (c1 == '>' && c2 == '=') { 658 shift(2); 659 return GE; 660 } 661 if (c1 == '!' && c2 == '=') { 662 shift(2); 663 return NE; 664 } 665 if (c1 == '+' && c2 == '+') { 666 shift(2); 667 if (m_terminator) 668 return AUTOPLUSPLUS; 669 return PLUSPLUS; 670 } 671 if (c1 == '-' && c2 == '-') { 672 shift(2); 673 if (m_terminator) 674 return AUTOMINUSMINUS; 675 return MINUSMINUS; 676 } 677 if (c1 == '=' && c2 == '=') { 678 shift(2); 679 return EQEQ; 680 } 681 if (c1 == '+' && c2 == '=') { 682 shift(2); 683 return PLUSEQUAL; 684 } 685 if (c1 == '-' && c2 == '=') { 686 shift(2); 687 return MINUSEQUAL; 688 } 689 if (c1 == '*' && c2 == '=') { 690 shift(2); 691 return MULTEQUAL; 692 } 693 if (c1 == '/' && c2 == '=') { 694 shift(2); 695 return DIVEQUAL; 696 } 697 if (c1 == '&' && c2 == '=') { 698 shift(2); 699 return ANDEQUAL; 700 } 701 if (c1 == '^' && c2 == '=') { 702 shift(2); 703 return XOREQUAL; 704 } 705 if (c1 == '%' && c2 == '=') { 706 shift(2); 707 return MODEQUAL; 708 } 709 if (c1 == '|' && c2 == '=') { 710 shift(2); 711 return OREQUAL; 712 } 713 if (c1 == '<' && c2 == '<') { 714 shift(2); 715 return LSHIFT; 716 } 717 if (c1 == '>' && c2 == '>') { 718 shift(2); 719 return RSHIFT; 720 } 721 if (c1 == '&' && c2 == '&') { 722 shift(2); 723 return AND; 724 } 725 if (c1 == '|' && c2 == '|') { 726 shift(2); 727 return OR; 728 } 729 730 switch (c1) { 731 case '=': 732 case '>': 733 case '<': 734 case ',': 735 case '!': 736 case '~': 737 case '?': 738 case ':': 739 case '.': 740 case '+': 741 case '-': 742 case '*': 743 case '/': 744 case '&': 745 case '|': 746 case '^': 747 case '%': 748 case '(': 749 case ')': 750 case '[': 751 case ']': 752 case ';': 753 shift(1); 754 return static_cast<int>(c1); 755 case '{': 756 charPos = m_position - 4; 757 shift(1); 758 return OPENBRACE; 759 case '}': 760 charPos = m_position - 4; 761 shift(1); 762 return CLOSEBRACE; 763 default: 764 return -1; 765 } 756 766 } 757 767 758 768 unsigned short Lexer::singleEscape(unsigned short c) 759 769 { 760 switch(c) {761 case 'b':762 return 0x08;763 case 't':764 return 0x09;765 case 'n':766 return 0x0A;767 case 'v':768 return 0x0B;769 case 'f':770 return 0x0C;771 case 'r':772 return 0x0D;773 case '"':774 return 0x22;775 case '\'':776 return 0x27;777 case '\\':778 return 0x5C;779 default:780 return c;781 }770 switch (c) { 771 case 'b': 772 return 0x08; 773 case 't': 774 return 0x09; 775 case 'n': 776 return 0x0A; 777 case 'v': 778 return 0x0B; 779 case 'f': 780 return 0x0C; 781 case 'r': 782 return 0x0D; 783 case '"': 784 return 0x22; 785 case '\'': 786 return 0x27; 787 case '\\': 788 return 0x5C; 789 default: 790 return c; 791 } 782 792 } 783 793 784 794 unsigned short Lexer::convertOctal(int c1, int c2, int c3) 785 795 { 786 return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0');796 return static_cast<unsigned short>((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); 787 797 } 788 798 789 799 unsigned char Lexer::convertHex(int c) 790 800 { 791 if (c >= '0' && c <= '9')792 return static_cast<unsigned char>(c - '0');793 if (c >= 'a' && c <= 'f')794 return static_cast<unsigned char>(c - 'a' + 10);795 return static_cast<unsigned char>(c - 'A' + 10);801 if (c >= '0' && c <= '9') 802 return static_cast<unsigned char>(c - '0'); 803 if (c >= 'a' && c <= 'f') 804 return static_cast<unsigned char>(c - 'a' + 10); 805 return static_cast<unsigned char>(c - 'A' + 10); 796 806 } 797 807 798 808 unsigned char Lexer::convertHex(int c1, int c2) 799 809 { 800 return ((convertHex(c1) << 4) + convertHex(c2));810 return ((convertHex(c1) << 4) + convertHex(c2)); 801 811 } 802 812 … … 829 839 bool Lexer::scanRegExp() 830 840 { 831 m_buffer16.clear(); 832 bool lastWasEscape = false; 833 bool inBrackets = false; 834 835 while (1) { 836 if (isLineTerminator() || current == -1) 837 return false; 838 else if (current != '/' || lastWasEscape == true || inBrackets == true) 839 { 840 // keep track of '[' and ']' 841 if (!lastWasEscape) { 842 if ( current == '[' && !inBrackets ) 843 inBrackets = true; 844 if ( current == ']' && inBrackets ) 845 inBrackets = false; 841 m_buffer16.clear(); 842 bool lastWasEscape = false; 843 bool inBrackets = false; 844 845 while (1) { 846 if (isLineTerminator() || m_current == -1) 847 return false; 848 else if (m_current != '/' || lastWasEscape == true || inBrackets == true) { 849 // keep track of '[' and ']' 850 if (!lastWasEscape) { 851 if ( m_current == '[' && !inBrackets ) 852 inBrackets = true; 853 if ( m_current == ']' && inBrackets ) 854 inBrackets = false; 855 } 856 record16(m_current); 857 lastWasEscape = 858 !lastWasEscape && (m_current == '\\'); 859 } else { // end of regexp 860 m_pattern = UString(m_buffer16); 861 m_buffer16.clear(); 862 shift(1); 863 break; 846 864 } 847 record16(current);848 lastWasEscape =849 !lastWasEscape && (current == '\\');850 } else { // end of regexp851 m_pattern = UString(m_buffer16);852 m_buffer16.clear();853 865 shift(1); 854 break; 855 } 856 shift(1); 857 } 858 859 while (isIdentPart(current)) { 860 record16(current); 861 shift(1); 862 } 863 m_flags = UString(m_buffer16); 864 865 return true; 866 } 867 868 while (isIdentPart(m_current)) { 869 record16(m_current); 870 shift(1); 871 } 872 m_flags = UString(m_buffer16); 873 874 return true; 866 875 } 867 876 … … 896 905 return identifier; 897 906 } 898 907 899 908 UString* Lexer::makeUString(const Vector<UChar>& buffer) 900 909 { -
trunk/JavaScriptCore/kjs/lexer.h
r34607 r35037 32 32 namespace KJS { 33 33 34 class Identifier;35 class RegExp;34 class Identifier; 35 class RegExp; 36 36 37 class Lexer : Noncopyable {38 public:39 void setCode(int startingLineNumber, PassRefPtr<SourceProvider> source);40 int lex(void* lvalp, void* llocp);37 class Lexer : Noncopyable { 38 public: 39 void setCode(int startingLineNumber, PassRefPtr<SourceProvider> source); 40 int lex(void* lvalp, void* llocp); 41 41 42 int lineNo() const { return yylineno; }42 int lineNo() const { return yylineno; } 43 43 44 bool prevTerminator() const { returnterminator; }44 bool prevTerminator() const { return m_terminator; } 45 45 46 enum State { Start, 47 IdentifierOrKeyword, 48 Identifier, 49 InIdentifierOrKeyword, 50 InIdentifier, 51 InIdentifierStartUnicodeEscapeStart, 52 InIdentifierStartUnicodeEscape, 53 InIdentifierPartUnicodeEscapeStart, 54 InIdentifierPartUnicodeEscape, 55 InSingleLineComment, 56 InMultiLineComment, 57 InNum, 58 InNum0, 59 InHex, 60 InOctal, 61 InDecimal, 62 InExponentIndicator, 63 InExponent, 64 Hex, 65 Octal, 66 Number, 67 String, 68 Eof, 69 InString, 70 InEscapeSequence, 71 InHexEscape, 72 InUnicodeEscape, 73 Other, 74 Bad }; 46 enum State { 47 Start, 48 IdentifierOrKeyword, 49 Identifier, 50 InIdentifierOrKeyword, 51 InIdentifier, 52 InIdentifierStartUnicodeEscapeStart, 53 InIdentifierStartUnicodeEscape, 54 InIdentifierPartUnicodeEscapeStart, 55 InIdentifierPartUnicodeEscape, 56 InSingleLineComment, 57 InMultiLineComment, 58 InNum, 59 InNum0, 60 InHex, 61 InOctal, 62 InDecimal, 63 InExponentIndicator, 64 InExponent, 65 Hex, 66 Octal, 67 Number, 68 String, 69 Eof, 70 InString, 71 InEscapeSequence, 72 InHexEscape, 73 InUnicodeEscape, 74 Other, 75 Bad 76 }; 75 77 76 bool scanRegExp();77 const UString& pattern() const { return m_pattern; }78 const UString& flags() const { return m_flags; }78 bool scanRegExp(); 79 const UString& pattern() const { return m_pattern; } 80 const UString& flags() const { return m_flags; } 79 81 80 static unsigned char convertHex(int);81 static unsigned char convertHex(int c1, int c2);82 static UChar convertUnicode(int c1, int c2, int c3, int c4);83 static bool isIdentStart(int);84 static bool isIdentPart(int);85 static bool isHexDigit(int);82 static unsigned char convertHex(int); 83 static unsigned char convertHex(int c1, int c2); 84 static UChar convertUnicode(int c1, int c2, int c3, int c4); 85 static bool isIdentStart(int); 86 static bool isIdentPart(int); 87 static bool isHexDigit(int); 86 88 87 bool sawError() const { returnerror; }89 bool sawError() const { return m_error; } 88 90 89 void clear();90 SourceRange sourceRange(int openBrace, int closeBrace) { return SourceRange(m_source, openBrace + 1, closeBrace); }91 void clear(); 92 SourceRange sourceRange(int openBrace, int closeBrace) { return SourceRange(m_source, openBrace + 1, closeBrace); } 91 93 92 private:93 friend struct JSGlobalData;94 Lexer(JSGlobalData*);95 ~Lexer();94 private: 95 friend struct JSGlobalData; 96 Lexer(JSGlobalData*); 97 ~Lexer(); 96 98 97 int yylineno; 98 bool done; 99 Vector<char> m_buffer8; 100 Vector<UChar> m_buffer16; 101 bool terminator; 102 bool restrKeyword; 103 // encountered delimiter like "'" and "}" on last run 104 bool delimited; 105 bool skipLF; 106 bool skipCR; 107 bool eatNextIdentifier; 108 int stackToken; 109 int lastToken; 99 void setDone(State); 100 void shift(unsigned int p); 101 void nextLine(); 102 int lookupKeyword(const char *); 110 103 111 State state; 112 void setDone(State); 113 unsigned int pos; 114 void shift(unsigned int p); 115 void nextLine(); 116 int lookupKeyword(const char *); 104 bool isWhiteSpace() const; 105 bool isLineTerminator(); 106 static bool isOctalDigit(int); 117 107 118 bool isWhiteSpace() const;119 bool isLineTerminator();120 static bool isOctalDigit(int);108 int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4); 109 static unsigned short singleEscape(unsigned short); 110 static unsigned short convertOctal(int c1, int c2, int c3); 121 111 122 int matchPunctuator(int& charPos, int c1, int c2, int c3, int c4);123 static unsigned short singleEscape(unsigned short);124 static unsigned short convertOctal(int c1, int c2, int c3);112 void record8(int); 113 void record16(int); 114 void record16(UChar); 125 115 126 void record8(int); 127 void record16(int); 128 void record16(UChar); 116 KJS::Identifier* makeIdentifier(const Vector<UChar>& buffer); 117 UString* makeUString(const Vector<UChar>& buffer); 129 118 130 KJS::Identifier* makeIdentifier(const Vector<UChar>& buffer);131 UString* makeUString(const Vector<UChar>& buffer);119 int yylineno; 120 int yycolumn; 132 121 133 RefPtr<SourceProvider> m_source; 134 const UChar* code; 135 unsigned int length; 136 int yycolumn; 137 int atLineStart; 138 bool error; 122 bool m_done; 123 Vector<char> m_buffer8; 124 Vector<UChar> m_buffer16; 125 bool m_terminator; 126 bool m_restrKeyword; 127 bool m_delimited; // encountered delimiter like "'" and "}" on last run 128 bool m_skipLF; 129 bool m_skipCR; 130 bool m_eatNextIdentifier; 131 int m_stackToken; 132 int m_lastToken; 139 133 140 // current and following unicode characters (int to allow for -1 for end-of-file marker)141 int current, next1, next2, next3;134 State m_state; 135 unsigned int m_position; 142 136 143 Vector<UString*> m_strings; 144 Vector<KJS::Identifier*> m_identifiers; 137 RefPtr<SourceProvider> m_source; 138 const UChar* m_code; 139 unsigned int m_length; 140 int m_atLineStart; 141 bool m_error; 145 142 146 JSGlobalData* m_globalData; 143 // current and following unicode characters (int to allow for -1 for end-of-file marker) 144 int m_current; 145 int m_next1; 146 int m_next2; 147 int m_next3; 147 148 148 UString m_pattern;149 UString m_flags;149 Vector<UString*> m_strings; 150 Vector<KJS::Identifier*> m_identifiers; 150 151 151 const HashTable mainTable; 152 }; 152 JSGlobalData* m_globalData; 153 154 UString m_pattern; 155 UString m_flags; 156 157 const HashTable m_mainTable; 158 }; 153 159 154 160 } // namespace KJS -
trunk/JavaScriptCore/profiler/CallIdentifier.h
r34962 r35037 55 55 56 56 #ifndef NDEBUG 57 operator const char* 57 operator const char*() const { return c_str(); } 58 58 const char* c_str() const { return m_name.UTF8String().c_str(); } 59 59 #endif -
trunk/JavaScriptCore/profiler/Profile.cpp
r34960 r35037 32 32 #include "ProfileNode.h" 33 33 #include "TreeProfile.h" 34 35 34 #include <stdio.h> 36 35 … … 99 98 100 99 // The console.profile that started this profile will be the first child. 101 void Profile::removeProfileStart() { 100 void Profile::removeProfileStart() 101 { 102 102 ProfileNode* currentNode = 0; 103 103 for (ProfileNode* next = m_head.get(); next; next = next->firstChild()) … … 118 118 119 119 // The console.profileEnd that stopped this profile will be the last child. 120 void Profile::removeProfileEnd() { 120 void Profile::removeProfileEnd() 121 { 121 122 ProfileNode* currentNode = 0; 122 123 for (ProfileNode* next = m_head.get(); next; next = next->lastChild()) … … 257 258 #endif 258 259 259 } 260 } // namespace KJS -
trunk/JavaScriptCore/profiler/ProfileNode.cpp
r34962 r35037 30 30 #include "ProfileNode.h" 31 31 32 #include "DateMath.h" 32 33 #include "Profiler.h" 33 #include "DateMath.h"34 35 34 #include <stdio.h> 36 35 … … 80 79 } 81 80 82 RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this); 81 RefPtr<ProfileNode> newChild = ProfileNode::create(callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head. 83 82 if (m_children.size()) 84 83 m_children.last()->setNextSibling(newChild.get()); … … 317 316 #endif 318 317 319 } 318 } // namespace KJS -
trunk/JavaScriptCore/profiler/ProfileNode.h
r34962 r35037 31 31 32 32 #include "CallIdentifier.h" 33 34 33 #include <wtf/Vector.h> 35 34 #include <wtf/RefCounted.h> … … 45 44 class ProfileNode : public RefCounted<ProfileNode> { 46 45 public: 47 static PassRefPtr<ProfileNode> create(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode) { 48 return adoptRef(new ProfileNode(callIdentifier, headNode, parentNode)); } 46 static PassRefPtr<ProfileNode> create(const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode) 47 { 48 return adoptRef(new ProfileNode(callIdentifier, headNode, parentNode)); 49 } 49 50 50 51 bool operator==(ProfileNode* node) { return m_callIdentifier == node->callIdentifier(); } … … 128 129 private: 129 130 ProfileNode(const CallIdentifier&, ProfileNode* headNode, ProfileNode* parentNode); 131 130 132 void startTimer(); 131 133 void resetChildrensSiblings(); 134 132 135 RefPtr<ProfileNode>* childrenBegin() { return m_children.begin(); } 133 136 RefPtr<ProfileNode>* childrenEnd() { return m_children.end(); } -
trunk/JavaScriptCore/profiler/Profiler.cpp
r35022 r35037 104 104 static inline void dispatchFunctionToProfiles(const Vector<RefPtr<Profile> >& profiles, Profile::ProfileFunction function, const CallIdentifier& callIdentifier, unsigned currentPageGroupIdentifier) 105 105 { 106 for (size_t i = 0; i < profiles.size(); ++i) 106 for (size_t i = 0; i < profiles.size(); ++i) { 107 107 if (profiles[i]->pageGroupIdentifier() == currentPageGroupIdentifier) 108 108 (profiles[i].get()->*function)(callIdentifier); 109 } 109 110 } 110 111 … … 164 165 } 165 166 166 } 167 } // namespace KJS -
trunk/JavaScriptCore/profiler/Profiler.h
r34800 r35037 51 51 void didFinishAllExecution(ExecState*); 52 52 53 void willExecute(ExecState* exec, JSObject* calledFunction);54 void willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber);55 void didExecute(ExecState* exec, JSObject* calledFunction);56 void didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber);53 void willExecute(ExecState*, JSObject* calledFunction); 54 void willExecute(ExecState*, const UString& sourceURL, int startingLineNumber); 55 void didExecute(ExecState*, JSObject* calledFunction); 56 void didExecute(ExecState*, const UString& sourceURL, int startingLineNumber); 57 57 58 58 const Vector<RefPtr<Profile> >& currentProfiles() { return m_currentProfiles; }; … … 69 69 70 70 protected: 71 virtual ~ProfilerClient() { }71 virtual ~ProfilerClient() { } 72 72 }; 73 73 -
trunk/JavaScriptCore/profiler/TreeProfile.cpp
r34960 r35037 44 44 } 45 45 46 } // namespace KJS 47 46 } // namespace KJS
Note:
See TracChangeset
for help on using the changeset viewer.