source: webkit/trunk/JavaScriptCore/parser/Nodes.cpp@ 63244

Last change on this file since 63244 was 63244, checked in by [email protected], 15 years ago

Bug 42182 - Change how numeric compare functions are detected

Reviewed by Oliver Hunt.

JavaScriptCore:

There are three problems with the current mechanism:

  • It requires that a function executable be bytecode compiled without being JIT generated (in order to copy the bytecode from the numeric compare function). This is a problem since we have an invariant when running with the JIT that functions are never bytecode compiled without also being JIT generated (after checking the codeblock we assume the function has JIT code). To help maintain this invariant
  • This implementation will prevent us from experimenting with alternate compilation paths which do not compile via bytecode.
  • It doesn't work. Functions passing more than two arguments will match if they are comparing their last two arguments, not the first two. Generally the mapping back from bytecode to semantics may be more complex then initially expected.
  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::generate):
(JSC::BytecodeGenerator::setIsNumericCompareFunction):
(JSC::BytecodeGenerator::argumentNumberFor):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::BlockNode::singleStatement):
(JSC::FunctionBodyNode::emitBytecode):

  • parser/Nodes.h:

(JSC::ExpressionNode::isSubtract):
(JSC::BinaryOpNode::lhs):
(JSC::BinaryOpNode::rhs):
(JSC::SubNode::isSubtract):
(JSC::ReturnNode::value):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):

  • runtime/JSGlobalData.h:

LayoutTests:

Test case.

  • fast/js/array-sort-numericCompare-expected.txt: Added.
  • fast/js/array-sort-numericCompare.html: Added.
  • fast/js/script-tests/array-sort-numericCompare.js: Added.

(doSort):
(dontSort):

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1/*
2* Copyright (C) 1999-2002 Harri Porten ([email protected])
3* Copyright (C) 2001 Peter Kelly ([email protected])
4* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5* Copyright (C) 2007 Cameron Zwarich ([email protected])
6* Copyright (C) 2007 Maks Orlovich
7* Copyright (C) 2007 Eric Seidel <[email protected]>
8*
9* This library is free software; you can redistribute it and/or
10* modify it under the terms of the GNU Library General Public
11* License as published by the Free Software Foundation; either
12* version 2 of the License, or (at your option) any later version.
13*
14* This library is distributed in the hope that it will be useful,
15* but WITHOUT ANY WARRANTY; without even the implied warranty of
16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17* Library General Public License for more details.
18*
19* You should have received a copy of the GNU Library General Public License
20* along with this library; see the file COPYING.LIB. If not, write to
21* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22* Boston, MA 02110-1301, USA.
23*
24*/
25
26#include "config.h"
27#include "Nodes.h"
28#include "NodeConstructors.h"
29
30#include "BytecodeGenerator.h"
31#include "CallFrame.h"
32#include "Debugger.h"
33#include "JIT.h"
34#include "JSFunction.h"
35#include "JSGlobalObject.h"
36#include "JSStaticScopeObject.h"
37#include "LabelScope.h"
38#include "Lexer.h"
39#include "Operations.h"
40#include "Parser.h"
41#include "PropertyNameArray.h"
42#include "RegExpObject.h"
43#include "SamplingTool.h"
44#include <wtf/Assertions.h>
45#include <wtf/RefCountedLeakCounter.h>
46#include <wtf/Threading.h>
47
48using namespace WTF;
49
50namespace JSC {
51
52
53// ------------------------------ StatementNode --------------------------------
54
55void StatementNode::setLoc(int firstLine, int lastLine)
56{
57 m_line = firstLine;
58 m_lastLine = lastLine;
59}
60
61// ------------------------------ SourceElements --------------------------------
62
63void SourceElements::append(StatementNode* statement)
64{
65 if (statement->isEmptyStatement())
66 return;
67 m_statements.append(statement);
68}
69
70StatementNode* SourceElements::singleStatement() const
71{
72 size_t size = m_statements.size();
73 return size == 1 ? m_statements[0] : 0;
74}
75
76// -----------------------------ScopeNodeData ---------------------------
77
78ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants)
79 : m_numConstants(numConstants)
80 , m_statements(statements)
81{
82 m_arena.swap(arena);
83 if (varStack)
84 m_varStack.swap(*varStack);
85 if (funcStack)
86 m_functionStack.swap(*funcStack);
87}
88
89// ------------------------------ ScopeNode -----------------------------
90
91ScopeNode::ScopeNode(JSGlobalData* globalData)
92 : StatementNode(globalData)
93 , ParserArenaRefCounted(globalData)
94 , m_features(NoFeatures)
95{
96}
97
98ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, CodeFeatures features, int numConstants)
99 : StatementNode(globalData)
100 , ParserArenaRefCounted(globalData)
101 , m_data(adoptPtr(new ScopeNodeData(globalData->parser->arena(), children, varStack, funcStack, numConstants)))
102 , m_features(features)
103 , m_source(source)
104{
105}
106
107StatementNode* ScopeNode::singleStatement() const
108{
109 return m_data->m_statements ? m_data->m_statements->singleStatement() : 0;
110}
111
112// ------------------------------ ProgramNode -----------------------------
113
114inline ProgramNode::ProgramNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
115 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
116{
117}
118
119PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
120{
121 RefPtr<ProgramNode> node = new ProgramNode(globalData, children, varStack, funcStack, source, features, numConstants);
122
123 ASSERT(node->data()->m_arena.last() == node);
124 node->data()->m_arena.removeLast();
125 ASSERT(!node->data()->m_arena.contains(node.get()));
126
127 return node.release();
128}
129
130// ------------------------------ EvalNode -----------------------------
131
132inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
133 : ScopeNode(globalData, source, children, varStack, funcStack, features, numConstants)
134{
135}
136
137PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants)
138{
139 RefPtr<EvalNode> node = new EvalNode(globalData, children, varStack, funcStack, source, features, numConstants);
140
141 ASSERT(node->data()->m_arena.last() == node);
142 node->data()->m_arena.removeLast();
143 ASSERT(!node->data()->m_arena.contains(node.get()));
144
145 return node.release();
146}
147
148// ------------------------------ FunctionBodyNode -----------------------------
149
150FunctionParameters::FunctionParameters(ParameterNode* firstParameter)
151{
152 for (ParameterNode* parameter = firstParameter; parameter; parameter = parameter->nextParam())
153 append(parameter->ident());
154}
155
156inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData)
157 : ScopeNode(globalData)
158{
159}
160
161inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
162 : ScopeNode(globalData, sourceCode, children, varStack, funcStack, features, numConstants)
163{
164}
165
166void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident)
167{
168 setSource(source);
169 finishParsing(FunctionParameters::create(firstParameter), ident);
170}
171
172void FunctionBodyNode::finishParsing(PassRefPtr<FunctionParameters> parameters, const Identifier& ident)
173{
174 ASSERT(!source().isNull());
175 m_parameters = parameters;
176 m_ident = ident;
177}
178
179FunctionBodyNode* FunctionBodyNode::create(JSGlobalData* globalData)
180{
181 return new FunctionBodyNode(globalData);
182}
183
184PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& sourceCode, CodeFeatures features, int numConstants)
185{
186 RefPtr<FunctionBodyNode> node = new FunctionBodyNode(globalData, children, varStack, funcStack, sourceCode, features, numConstants);
187
188 ASSERT(node->data()->m_arena.last() == node);
189 node->data()->m_arena.removeLast();
190 ASSERT(!node->data()->m_arena.contains(node.get()));
191
192 return node.release();
193}
194
195} // namespace JSC
Note: See TracBrowser for help on using the repository browser.